home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / proc / procMigrate.c < prev    next >
C/C++ Source or Header  |  1991-07-26  |  79KB  |  2,877 lines

  1. /* 
  2.  * procMigrate.c --
  3.  *
  4.  *    Routines for process migration.  These provide the system
  5.  *    call interface to initiate migration and routines to transfer
  6.  *    data from the host on which the process is currently executing
  7.  *    to the host to which it is migrating.  The routines that accept
  8.  *    this data are in procRemote.c.  
  9.  *
  10.  * Copyright 1986, 1988, 1989 Regents of the University of California
  11.  * Permission to use, copy, modify, and distribute this
  12.  * software and its documentation for any purpose and without
  13.  * fee is hereby granted, provided that the above copyright
  14.  * notice appear in all copies.  The University of California
  15.  * makes no representations about the suitability of this
  16.  * software for any purpose.  It is provided "as is" without
  17.  * express or implied warranty.
  18.  */
  19.  
  20. #ifndef lint
  21. static char rcsid[] = "$Header: /sprite/src/kernel/proc/RCS/procMigrate.c,v 9.32 91/07/26 16:59:51 shirriff Exp $ SPRITE (Berkeley)";
  22. #endif /* not lint */
  23.  
  24.  
  25. #include <sprite.h>
  26. #include <mach.h>
  27. #include <proc.h>
  28. #include <procInt.h>
  29. #include <procMigrate.h>
  30. #include <migrate.h>
  31. #include <migVersion.h>
  32. #include <fs.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sig.h>
  36. #include <spriteTime.h>
  37. #include <trace.h>
  38. #include <list.h>
  39. #include <byte.h>
  40. #include <vm.h>
  41. #include <sys.h>
  42. #include <dbg.h>
  43. #include <rpc.h>
  44. #include <prof.h>
  45. #include <sched.h>
  46. #include <sync.h>
  47. #include <sysSysCall.h>
  48. #include <timer.h>
  49. #include <stdio.h>
  50. #include <bstring.h>
  51. #include <recov.h>
  52.  
  53. Sync_Condition    migrateCondition;
  54. Sync_Condition    evictCondition;
  55. static    Sync_Lock    migrateLock = Sync_LockInitStatic("Proc:migrateLock");
  56. #define    LOCKPTR &migrateLock
  57. static  Time        timeEvictionStarted;
  58.  
  59. int proc_MigDebugLevel = 2;
  60.  
  61. Trace_Header proc_TraceHeader;
  62. Trace_Header *proc_TraceHdrPtr = (Trace_Header *)NIL;
  63. Boolean proc_DoTrace = FALSE;
  64. Boolean proc_DoCallTrace = FALSE;
  65.  
  66. /*
  67.  * Allocate variables and structures relating to statistics.
  68.  * Updating variables is done under a monitor.  Currently, each update
  69.  * is typically done via a monitored procedure call, though it may be
  70.  * preferable to in-line the monitors (if this is permissible at some point)
  71.  * or combine multiple operations in a single procedure.
  72.  * Some of the statistics are kept even in CLEAN kernels because they affect
  73.  * the kernel's notion of whether eviction is necessary.  Also, the timing
  74.  * statistics are useful for benchmarking CLEAN kernels.   Things that are
  75.  * purely for statistics gathering are conditioned on CLEAN as well as
  76.  * proc_MigDoStats.
  77.  */  
  78. Boolean proc_MigDoStats = TRUE;
  79. Proc_MigStats proc_MigStats;
  80.  
  81. /*
  82.  * True if we should convert a SIG_DEBUG into a SIG_KILL for migrated
  83.  * processes.
  84.  */
  85. Boolean proc_KillMigratedDebugs = TRUE;
  86.  
  87. int proc_AllowMigrationState = PROC_MIG_ALLOW_DEFAULT;
  88.  
  89. /*
  90.  * Declare some variables from corresponding constants.  This permits
  91.  * them to be modified using the debugger or mainHook.  
  92.  */
  93. int proc_MigrationVersion = PROC_MIGRATE_VERSION;
  94. static int statsVersion = PROC_MIG_STATS_VERSION;
  95.  
  96. /*
  97.  * Procedures internal to this file
  98.  */
  99.  
  100. static ReturnStatus GetProcEncapSize _ARGS_((Proc_ControlBlock *procPtr,
  101.                 int hostID, Proc_EncapInfo *infoPtr));
  102. static ReturnStatus EncapProcState _ARGS_((Proc_ControlBlock *procPtr,
  103.                 int hostID, Proc_EncapInfo *infoPtr,
  104.                 Address bufPtr));
  105. static ReturnStatus DeencapProcState _ARGS_((Proc_ControlBlock *procPtr,
  106.                 Proc_EncapInfo *infoPtr, Address bufPtr));
  107.  
  108. static void         AbortMigration _ARGS_((Proc_ControlBlock *procPtr));
  109.  
  110. static void         SuspendCallback _ARGS_((ClientData data,
  111.                 Proc_CallInfo *callInfoPtr));
  112.  
  113. /*
  114.  * Procedures for statistics gathering
  115.  */
  116. static ENTRY void    AddMigrateTime _ARGS_((Time time, unsigned int *totalPtr,
  117.                 unsigned int *squaredTotalPtr));
  118. static ENTRY void    AccessStats _ARGS_((Proc_MigStats *copyPtr));
  119. static ENTRY Boolean EvictionStarted _ARGS_((void));
  120. static ENTRY void    WaitForEviction _ARGS_((void));
  121. static ENTRY ReturnStatus WaitForMigration _ARGS_((void));
  122.  
  123.  
  124. #ifdef DEBUG
  125. int proc_MemDebug = 0;
  126. #endif /* DEBUG */
  127. /*
  128.  * Define the structure for keeping track of callbacks for migrating
  129.  * a process.  (This is done after procedure declarations since
  130.  * some things are static and we need the forward reference.)
  131.  *
  132.  * See the comments in Proc_MigrateTrap for further explanation.
  133.  */
  134. typedef struct {
  135.     ReturnStatus (*preFunc)();       /* function to call when initiating
  136.                       migration (returning size); should not
  137.                       have side-effects requiring further
  138.                       callback */
  139.     ReturnStatus (*encapFunc)();   /* function to call to encapsulate data */
  140.     ReturnStatus (*deencapFunc)(); /* function to call to deencapsulate
  141.                     data on other end */
  142.     ReturnStatus (*postFunc)();       /* function to call after migration
  143.                       completes or fails */
  144.     Proc_EncapToken token;       /* identifier to match encap and deencap
  145.                       functions between two hosts */
  146.     int whenNeeded;           /* flags defined below indicate when
  147.                       needed */
  148. } EncapCallback;
  149.  
  150. /*
  151.  * Flags for the whenNeeded field:
  152.  */
  153. #define MIG_ENCAP_MIGRATE 1
  154. #define MIG_ENCAP_EXEC 2
  155. #define MIG_ENCAP_ALWAYS (MIG_ENCAP_MIGRATE | MIG_ENCAP_EXEC)
  156. /*    
  157.  * Set up the functions to be called.
  158.  */
  159. static EncapCallback encapCallbacks[] = {
  160.     { GetProcEncapSize, EncapProcState, DeencapProcState, NULL,
  161.       PROC_MIG_ENCAP_PROC, MIG_ENCAP_ALWAYS},
  162.     { ProcExecGetEncapSize, ProcExecEncapState, ProcExecDeencapState,
  163.       ProcExecFinishMigration,
  164.       PROC_MIG_ENCAP_EXEC, MIG_ENCAP_EXEC},
  165. #ifdef notdef
  166.     { Vm_InitiateMigration, Vm_EncapState, Vm_DeencapState, Vm_FinishMigration,
  167.       PROC_MIG_ENCAP_VM, MIG_ENCAP_MIGRATE},
  168. #endif
  169.     { Vm_InitiateMigration, Vm_EncapState, Vm_DeencapState, NULL,
  170.       PROC_MIG_ENCAP_VM, MIG_ENCAP_MIGRATE},
  171.     { Fs_InitiateMigration, Fs_EncapFileState, Fs_DeencapFileState, NULL,
  172.       PROC_MIG_ENCAP_FS, MIG_ENCAP_ALWAYS},
  173.     { Mach_GetEncapSize, Mach_EncapState, Mach_DeencapState, NULL,
  174.       PROC_MIG_ENCAP_MACH, MIG_ENCAP_ALWAYS},
  175.     { Prof_GetEncapSize, Prof_EncapState, Prof_DeencapState, NULL,
  176.       PROC_MIG_ENCAP_PROF, MIG_ENCAP_ALWAYS},
  177.     { Sig_GetEncapSize, Sig_EncapState, Sig_DeencapState, NULL,
  178.       PROC_MIG_ENCAP_SIG, MIG_ENCAP_ALWAYS},
  179. };
  180.  
  181. #define BREAKS_KDBX
  182. #ifdef BREAKS_KDBX
  183. static struct {
  184.     char *preFunc;       /* name of function to call when initiating
  185.                       migration */
  186.     char *encapFunc;    /* name of function to call to encapsulate */
  187.     char *deencapFunc;    /* name of function to call to deencapsulate */
  188.     char *postFunc;    /* name of function to call when done */
  189. } callbackNames[] = {
  190.     { "GetProcEncapSize", "EncapProcState", "DeencapProcState", NULL},
  191.     { "ProcExecGetEncapSize", "ProcExecEncapState", "ProcExecDeencapState", "ProcExecFinishMigration"},
  192.     { "Vm_InitiateMigration", "Vm_EncapState", "Vm_DeencapState",
  193.       NULL},
  194.     { "Fs_InitiateMigration", "Fs_EncapFileState", "Fs_DeencapFileState",
  195.       "Fs_MigDone"},
  196.     { "Mach_InitiateMigration", "Mach_EncapState", "Mach_DeencapState", NULL},
  197.     { "Prof_InitiateMigration", "Prof_EncapState", "Prof_DeencapState", NULL},
  198.     { "Sig_InitiateMigration", "Sig_EncapState", "Sig_DeencapState", NULL}
  199. };
  200. #endif
  201.  
  202. /*
  203.  * Define a macro for squaring a time without automatically overflowing
  204.  * due to the large number of microseconds being multiplied.
  205.  * The square of (X + Y/1000000) is X^2 + 2XY/1000000 + Y^2/10^12.
  206.  * XXX not used -- switched to single integers as milliseconds.  
  207.  */
  208. #define SQUARE_TIME(time, squaredTime) \
  209.     squaredTime.seconds = time.seconds * time.seconds; \
  210.     squaredTime.microseconds = 2 * time.seconds * time.microseconds + \
  211.                              time.microseconds * time.microseconds / 1000000; \
  212.     while (squaredTime.microseconds > 1000000) { \
  213.     squaredTime.seconds++; \
  214.     squaredTime.microseconds -= 1000000; \
  215.     } \
  216.  
  217.  
  218.  
  219.  
  220. /*
  221.  *----------------------------------------------------------------------
  222.  *
  223.  * Proc_MigInit --
  224.  *
  225.  *    Initialize data structures relating to process migration.
  226.  *    This procedure is called at boot time.
  227.  *    Sets up statistics gathering and recovery code.
  228.  *
  229.  * Results:
  230.  *    None.
  231.  *
  232.  * Side effects:
  233.  *    Calls other initialization procedures.
  234.  *
  235.  *----------------------------------------------------------------------
  236.  */
  237.  
  238. void
  239. Proc_MigInit()
  240. {
  241.     AccessStats((Proc_MigStats *) NIL);
  242.     ProcRecovInit();
  243. }
  244.  
  245.  
  246.  
  247. /*
  248.  *----------------------------------------------------------------------
  249.  *
  250.  * Proc_Migrate --
  251.  *
  252.  *    Migrates a process to another workstation.  The process may be
  253.  *        PROC_MY_PID, PROC_ALL_PROCESSES, or a process ID.
  254.  *        PROC_ALL_PROCESSES implies evicting all foreign processes, in
  255.  *        which case the hostID is ignored.  The workstation may be
  256.  *        PROC_MIG_ANY or a particular workstation.  (For now, the
  257.  *        workstation argument must be a specific workstation.)
  258.  *
  259.  *     This procedure implements the system call by the same name.
  260.  *
  261.  * Results:
  262.  *    PROC_INVALID_PID -    the pid argument was illegal.
  263.  *    PROC_INVALID_NODE_ID -    the host argument was illegal.
  264.  *    GEN_NO_PERMISSION -    the user or process is not permitted to
  265.  *                migrate.
  266.  *    Other results may be returned from the VM and RPC modules.
  267.  *
  268.  * Side effects:
  269.  *    The specified process is migrated to another workstation.
  270.  *
  271.  *----------------------------------------------------------------------
  272.  */
  273.  
  274. ReturnStatus
  275. Proc_Migrate(pid, hostID)
  276.     Proc_PID pid;
  277.     int         hostID;
  278. {
  279.     register Proc_ControlBlock *procPtr;
  280.     ReturnStatus status;
  281.     Proc_TraceRecord record;
  282.     Boolean migrateSelf = FALSE;
  283.     int permMask;
  284.  
  285.     /*
  286.      * It is possible for a process to try to migrate onto the machine
  287.      * on which it is currently executing.
  288.      */
  289.  
  290.     if (hostID == rpc_SpriteID) {
  291.     return(SUCCESS);
  292.     }
  293.     
  294.     if (Proc_ComparePIDs(pid, PROC_ALL_PROCESSES)) {
  295.     procPtr = Proc_GetEffectiveProc();
  296.     if (procPtr->effectiveUserID != 0) {
  297.         return(GEN_NO_PERMISSION);
  298.     }
  299.     status = Proc_EvictForeignProcs();
  300.     return(status);
  301.     }
  302.     
  303.     if (hostID <= 0 || hostID > NET_NUM_SPRITE_HOSTS) {
  304.     return(GEN_INVALID_ARG);
  305.     }
  306.  
  307.     if (Proc_ComparePIDs(pid, PROC_MY_PID)) {
  308.     migrateSelf = TRUE;
  309.     procPtr = Proc_GetActualProc();
  310.     if (procPtr == (Proc_ControlBlock *) NIL) {
  311.         panic("Proc_Migrate: procPtr == NIL\n");
  312.     }
  313.     Proc_Lock(procPtr);
  314.     pid = procPtr->processID;
  315.     } else {
  316.     procPtr = Proc_LockPID(pid);
  317.     if (procPtr == (Proc_ControlBlock *) NIL) {
  318.         return (PROC_INVALID_PID);
  319.     }
  320.     }
  321.  
  322.  
  323.     if (proc_MigDebugLevel > 3) {
  324.     printf("Proc_Migrate: migrate process %x to host %d.\n",
  325.            procPtr->processID, hostID);
  326.     }
  327.  
  328.     /*
  329.      * Do some sanity checking.  
  330.      */
  331.     if ((procPtr->state == PROC_DEAD) || (procPtr->state == PROC_EXITING) ||
  332.     (procPtr->genFlags & PROC_DYING)) {
  333.     if (proc_MigDebugLevel > 3) {
  334.         printf("Proc_Migrate: process %x has exited.\n",
  335.                pid);
  336.     }
  337.     Proc_Unlock(procPtr);
  338.     return(PROC_INVALID_PID);
  339.     }
  340.     if (procPtr->state == PROC_MIGRATED) {
  341.     if (proc_MigDebugLevel > 1) {
  342.         printf("Proc_Migrate: process %x has already migrated.\n",
  343.                pid);
  344.     }
  345.     Proc_Unlock(procPtr);
  346.     return(PROC_INVALID_PID);
  347.     }
  348.     
  349.     if (procPtr->genFlags & PROC_FOREIGN) {
  350.     if (proc_MigDebugLevel > 0) {
  351.         printf("Proc_Migrate: process %x is foreign... can't migrate yet.\n",
  352.                procPtr->processID);
  353.     }
  354.     Proc_Unlock(procPtr);
  355.     return(PROC_INVALID_PID);
  356.     }
  357.     if (procPtr->genFlags & PROC_DONT_MIGRATE) {
  358.     if (proc_MigDebugLevel > 0) {
  359.         printf("Proc_Migrate: process %x is not allowed to migrate.\n",
  360.                pid);
  361.     }
  362.     Proc_Unlock(procPtr);
  363.     return(GEN_NO_PERMISSION);
  364.     }
  365.     
  366.     if (procPtr->argString == (char *) NIL) {
  367.     if (proc_MigDebugLevel > 0) {
  368.         printf("Proc_Migrate: process %x has no argument string: can't migrate.\n",
  369.                pid);
  370.     }
  371.     Proc_Unlock(procPtr);
  372.     return(PROC_INVALID_PID);
  373.     }
  374.     
  375.     if (procPtr->userID == PROC_SUPER_USER_ID) {
  376.     permMask = PROC_MIG_EXPORT_ROOT;
  377.     } else {
  378.     permMask = PROC_MIG_EXPORT_ALL;
  379.     }
  380.  
  381.     if ((proc_AllowMigrationState & permMask) != permMask) {
  382.     if (proc_MigDebugLevel > 0) {
  383.         printf("Proc_Migrate: user does not have permission to migrate.\n");
  384.     }
  385.     Proc_Unlock(procPtr);
  386.     return(GEN_NO_PERMISSION);
  387.     }
  388.     
  389. #ifndef CLEAN
  390.     if (proc_DoTrace && proc_MigDebugLevel > 0) {
  391.     record.processID = procPtr->processID;
  392.     record.flags = PROC_MIGTRACE_START | PROC_MIGTRACE_HOME;
  393.     record.info.filler = NIL;
  394.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_BEGIN_MIG,
  395.              (ClientData) &record);
  396.     }
  397. #endif /* CLEAN */
  398.    
  399.     /*
  400.      * Contact the remote workstation to establish communication and
  401.      * verify that migration is permissible.
  402.      */
  403.     
  404.     status = ProcInitiateMigration(procPtr, hostID);
  405.  
  406.  
  407.     if (status != SUCCESS) {
  408.     Proc_Unlock(procPtr);
  409. #ifndef CLEAN
  410.     if (proc_MigDoStats) {
  411.         PROC_MIG_INC_STAT(errors);
  412.     }
  413. #endif /* CLEAN */
  414.     return(status);
  415.     }
  416.  
  417.     
  418.     Proc_FlagMigration(procPtr, hostID, FALSE);
  419.  
  420.     Proc_Unlock(procPtr);
  421.  
  422.     /*
  423.      * If migrating another process, wait for it to migrate.
  424.      */
  425.     if (!migrateSelf) {
  426.     status = Proc_WaitForMigration(pid);
  427.     } else {
  428.     status = SUCCESS;
  429.     }
  430.  
  431.     /*
  432.      * Note: the "end migration" trace record is inserted by the MigrateTrap
  433.      * routine to get around the issue of waiting for oneself to migrate.
  434.      * (Otherwise, since we can't wait here for the current process to
  435.      * migrate -- only a different process -- we wouldn't be able to insert
  436.      * the trace record at the right time.)
  437.      */
  438.      
  439.     return(status);
  440. }
  441.  
  442.  
  443. /*
  444.  *----------------------------------------------------------------------
  445.  *
  446.  * Proc_MigrateTrap --
  447.  *
  448.  *    Transfer the state of a process once it has reached a state with no
  449.  *    relevant information on the kernel stack.  This is done following a
  450.  *    kernel call, when the process can migrate and immediately return
  451.  *    to user mode and there is no relevant information on the kernel
  452.  *    stack.  
  453.  *
  454.  * Results:
  455.  *    No value is returned.
  456.  *
  457.  * Side effects:
  458.  *    The process state is transferred by performing callbacks
  459.  *    to each module with state to transfer.
  460.  *
  461.  *----------------------------------------------------------------------
  462.  */
  463.  
  464. void
  465. Proc_MigrateTrap(procPtr)
  466.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  467. {
  468.     int hostID;            /* host to which it migrates */
  469.     ReturnStatus status = FAILURE;
  470.     Proc_TraceRecord record;
  471.     Boolean foreign = FALSE;
  472.     Boolean evicting = FALSE;
  473.     Address buffer;
  474.     Address bufPtr;
  475.     int bufSize;
  476.     register int i;
  477.     Proc_EncapInfo info[PROC_MIG_NUM_CALLBACKS];
  478.     Proc_EncapInfo *infoPtr;
  479.     ProcMigCmd cmd;
  480.     Proc_MigBuffer inBuf;
  481.     int failed;
  482.     Time startTime;
  483.     Time endTime;
  484.     Time timeDiff;
  485.     unsigned int *timePtr;
  486.     unsigned int *squaredTimePtr;
  487.     int whenNeeded;
  488.     Boolean exec;
  489.     Proc_PID pid;
  490.  
  491.     Proc_Lock(procPtr);
  492.  
  493.     if (procPtr->genFlags & PROC_FOREIGN) {
  494.     foreign = TRUE;
  495.     if (procPtr->migFlags & PROC_EVICTING) {
  496.         evicting = TRUE;
  497.     }
  498.     }
  499.     if (procPtr->genFlags & PROC_REMOTE_EXEC_PENDING) {
  500.     whenNeeded = MIG_ENCAP_EXEC;
  501.     exec = TRUE;
  502.     } else {
  503.     whenNeeded = MIG_ENCAP_MIGRATE;
  504.     exec = FALSE;
  505.     }
  506.     if (proc_MigDoStats) {
  507.     Timer_GetTimeOfDay(&startTime, (int *) NIL, (Boolean *) NIL);
  508.     }
  509.     pid = procPtr->processID;
  510.     if (proc_DoTrace && proc_MigDebugLevel > 1) {
  511.     record.processID = pid;
  512.     record.flags = PROC_MIGTRACE_START;
  513.     if (!foreign) {
  514.         record.flags |= PROC_MIGTRACE_HOME;
  515.     }
  516.     record.info.filler = NIL;
  517.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_MIGTRAP,
  518.              (ClientData) &record);
  519.     }
  520.    
  521.     procPtr->genFlags = (procPtr->genFlags &
  522.              ~(PROC_MIG_PENDING | PROC_MIGRATION_DONE) |
  523.              PROC_MIGRATING);
  524.     
  525.     hostID = procPtr->peerHostID;
  526.     bufSize = 0;
  527.  
  528.     /*
  529.      * Go through the list of callbacks to generate the size of the buffer
  530.      * we'll need.  In unusual circumstances, a caller may return a status
  531.      * other than SUCCESS. In this case, the process should be continuable!
  532.      */
  533.     for (i = 0; i < PROC_MIG_NUM_CALLBACKS; i++) {
  534.     if (!(encapCallbacks[i].whenNeeded & whenNeeded)) {
  535.         continue;
  536.     }
  537.     infoPtr = &info[i];
  538.     infoPtr->token = encapCallbacks[i].token;
  539.     infoPtr->processed = 0;
  540.     infoPtr->special = 0;
  541.     if (proc_MigDebugLevel > 5) {
  542.         printf("Calling preFunc %d\n", i);
  543.     }
  544.     status = (*encapCallbacks[i].preFunc)(procPtr, hostID, infoPtr);
  545.     if (status == SUCCESS && infoPtr->special) {
  546.         /*
  547.          * This is where we'd like to handle special cases like shared
  548.          * memory processes.  For now, bail out.
  549.          */
  550.         status = GEN_NOT_IMPLEMENTED;
  551.     }
  552.     if (status != SUCCESS) {
  553.         printf("Warning: Proc_MigrateTrap: error returned by encapsulation procedure %s:\n\t%s.\n",
  554. #ifdef BREAKS_KDBX
  555.            callbackNames[i].preFunc,
  556. #else /* BREAKS_KDBX */
  557.            "(can't get name)", 
  558. #endif /* BREAKS_KDBX */
  559.            Stat_GetMsg(status));
  560.         if (exec) {
  561.         goto failure;
  562.         } else {
  563.         AbortMigration(procPtr);
  564.         }
  565.         return;
  566.     }
  567.     bufSize += infoPtr->size + sizeof(Proc_EncapInfo);
  568.     }
  569.     if (proc_MigDebugLevel > 5) {
  570.     printf("Buffer size is %d\n", bufSize);
  571.     }
  572.     buffer = malloc(bufSize);
  573.     if (proc_MigDebugLevel > 5) {
  574.     printf("past malloc\n", bufSize);
  575.     }
  576.     bufPtr = buffer;
  577.     failed = 0;
  578.  
  579.     /*
  580.      * This time, go through the list of callbacks to fill in the
  581.      * encapsulated data.  From this point on, failed indicates
  582.      * that the process will be killed.
  583.      */
  584.     for (i = 0; i < PROC_MIG_NUM_CALLBACKS; i++) {
  585.     if (!(encapCallbacks[i].whenNeeded & whenNeeded)) {
  586.         continue;
  587.     }
  588.     infoPtr = &info[i];
  589.     bcopy((Address) infoPtr, bufPtr, sizeof(Proc_EncapInfo));
  590.     bufPtr += sizeof(Proc_EncapInfo);
  591.     if (proc_MigDebugLevel > 5) {
  592.         printf("Calling encapFunc %d\n", i);
  593.     }
  594.     status = (*encapCallbacks[i].encapFunc)(procPtr, hostID, infoPtr,
  595.                         bufPtr);
  596. #ifdef lint
  597.     status = EncapProcState(procPtr, hostID, infoPtr, bufPtr);
  598.     status = ProcExecEncapState(procPtr, hostID, infoPtr, bufPtr);
  599.     status = Vm_EncapState(procPtr, hostID, infoPtr, bufPtr);
  600.     status = Fs_EncapFileState(procPtr, hostID, infoPtr, bufPtr);
  601.     status = Mach_EncapState(procPtr, hostID, infoPtr, bufPtr);
  602.     status = Prof_EncapState(procPtr, hostID, infoPtr, bufPtr);
  603.     status = Sig_EncapState(procPtr, hostID, infoPtr, bufPtr);
  604. #endif /* lint */
  605.     if (status != SUCCESS) {
  606.         printf("Warning: Proc_MigrateTrap: error returned by encapsulation procedure %s:\n\t%s.\n",
  607. #ifdef BREAKS_KDBX
  608.            callbackNames[i].encapFunc,
  609. #else /* BREAKS_KDBX */
  610.            "(can't get name)", 
  611. #endif /* BREAKS_KDBX */
  612.            Stat_GetMsg(status));
  613.         failed = 1;
  614.         break;
  615.     }
  616.     bufPtr += infoPtr->size;
  617.     infoPtr->processed = 1;
  618.     }
  619.  
  620.     Proc_Unlock(procPtr);
  621.     /*
  622.      * Send the encapsulated data in the buffer to the other host.  
  623.      */
  624.     if (!failed) {
  625.     /*
  626.      * Set up for the RPC.
  627.      */
  628.     cmd.command = PROC_MIGRATE_CMD_ENTIRE;
  629.     cmd.remotePid = procPtr->peerProcessID;
  630.     inBuf.size = bufSize;
  631.     inBuf.ptr = buffer;
  632.     if (proc_MigDoStats) {
  633.         Proc_MigAddToCounter((bufSize + 1023) / 1024, &proc_MigStats.varStats.rpcKbytes, &proc_MigStats.squared.rpcKbytes);
  634.     }
  635.  
  636.     if (proc_MigDebugLevel > 5) {
  637.         printf("Sending encapsulated state.\n");
  638.     }
  639.     status = ProcMigCommand(procPtr->peerHostID, &cmd, &inBuf,
  640.                 (Proc_MigBuffer *) NIL);
  641.  
  642.     if (status != SUCCESS) {
  643.         printf("Warning: Proc_MigrateTrap: error encountered sending encapsulated state:\n\t%s.\n",
  644.            Stat_GetMsg(status));
  645.         failed = 1;
  646.     }
  647.     }
  648.     /*
  649.      * Finally, go through the list of callbacks to clean up.  Only call
  650.      * routines that were processed last time (in the case of failure
  651.      * partway through).  Note that the process pointer is UNLOCKED
  652.      * during these callbacks (as well as the RPC to transfer state).
  653.      * This is primarily because Vm_FinishMigration is the only callback
  654.      * so far and it needs it unlocked, and we have to unlock for the rpc
  655.      * anyway so that we don't deadlock on the process once the migrated
  656.      * version resumes (a side effect of the RPC).
  657.      */
  658.     bufPtr = buffer;
  659.     for (i = 0; i < PROC_MIG_NUM_CALLBACKS; i++) {
  660.     if (!(encapCallbacks[i].whenNeeded & whenNeeded)) {
  661.         continue;
  662.     }
  663.     infoPtr = &info[i];
  664.     if (infoPtr->processed != 1) {
  665.         continue;
  666.     }
  667.     bufPtr += sizeof(Proc_EncapInfo);
  668.     if (encapCallbacks[i].postFunc != NULL) {
  669.         if (proc_MigDebugLevel > 5) {
  670.         printf("Calling postFunc %d\n", i);
  671.         }
  672.         status = (*encapCallbacks[i].postFunc)(procPtr, hostID, infoPtr,
  673.                            bufPtr, failed);
  674. #ifdef lint
  675.         status = Vm_FinishMigration(procPtr, hostID, infoPtr, bufPtr,
  676.                     failed);
  677. #endif /* lint */
  678.     }
  679.     if (status != SUCCESS) {
  680.         failed = 1;
  681.     }
  682.     bufPtr += infoPtr->size;
  683.     }
  684.     free(buffer);
  685.  
  686.     if (failed) {
  687.     goto failure;
  688.     }
  689.  
  690.     Proc_Lock(procPtr);
  691.  
  692.     procPtr->genFlags = (procPtr->genFlags &
  693.              ~(PROC_REMOTE_EXEC_PENDING| PROC_MIG_ERROR)) |
  694.                  PROC_MIGRATION_DONE;
  695.     Proc_Unlock(procPtr);
  696.  
  697.  
  698.     /*
  699.      * Tell the other host to resume the process.
  700.      */
  701.     cmd.command = PROC_MIGRATE_CMD_RESUME;
  702.     cmd.remotePid = procPtr->peerProcessID;
  703.  
  704.     if (proc_MigDebugLevel > 5) {
  705.     printf("Issuing resume command.\n");
  706.     }
  707.     status = ProcMigCommand(procPtr->peerHostID, &cmd, (Proc_MigBuffer *) NIL,
  708.                 (Proc_MigBuffer *) NIL);
  709.  
  710.     if (status != SUCCESS) {
  711.     printf("Warning: Proc_MigrateTrap: error encountered resuming process:\n\t%s.\n",
  712.            Stat_GetMsg(status));
  713.     goto failure;
  714.     }
  715.  
  716.     /*
  717.      * If not migrating back home, note the dependency on the other host.
  718.      * Otherwise, forget the dependency after eviction.
  719.      */
  720.     if (!foreign) {
  721.     ProcMigAddDependency(procPtr->processID, procPtr->peerProcessID);
  722.     } else {
  723.     ProcMigRemoveDependency(procPtr->processID, TRUE);
  724.     }
  725.  
  726.  
  727.     /*
  728.      * It's finally safe to indicate that the process isn't in the middle
  729.      * of migration.  For example, anyone waiting to send a signal to the
  730.      * process should wait until this point so the process is executing
  731.      * on the other host.
  732.      */
  733.     Proc_Lock(procPtr);
  734.     procPtr->genFlags &= ~PROC_MIGRATING;
  735.     procPtr->migFlags &= ~PROC_EVICTING;
  736.     Proc_Unlock(procPtr);
  737.  
  738.     ProcMigWakeupWaiters();
  739.     if (proc_DoTrace && proc_MigDebugLevel > 1) {
  740.     record.flags = (foreign ? 0 : PROC_MIGTRACE_HOME);
  741.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_MIGTRAP,
  742.              (ClientData) &record);
  743.     }
  744.  
  745.     if (proc_MigDoStats) {
  746.     Timer_GetTimeOfDay(&endTime, (int *) NIL, (Boolean *) NIL);
  747.     Time_Subtract(endTime, startTime, &timeDiff);
  748.     if (whenNeeded == MIG_ENCAP_MIGRATE) {
  749.         if (evicting) {
  750.         timePtr = &proc_MigStats.varStats.timeToEvict;
  751.         squaredTimePtr = &proc_MigStats.squared.timeToEvict;
  752.         } else {
  753.         timePtr = &proc_MigStats.varStats.timeToMigrate;
  754.         squaredTimePtr = &proc_MigStats.squared.timeToMigrate;
  755.         }
  756.     } else {
  757.         timePtr = &proc_MigStats.varStats.timeToExec;
  758.         squaredTimePtr = &proc_MigStats.squared.timeToExec;
  759.     }
  760.     AddMigrateTime(timeDiff, timePtr, squaredTimePtr);
  761.     }
  762.     if (proc_DoTrace && proc_MigDebugLevel > 0 && !foreign) {
  763.     record.processID = pid;
  764.     record.flags = PROC_MIGTRACE_HOME;
  765.     record.info.filler = NIL;
  766.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_END_MIG,
  767.              (ClientData) &record);
  768.     }
  769.  
  770.     /*
  771.      * Check for asynchronous errors coming in after we resumed on the other
  772.      * host.
  773.      */
  774.     Proc_Lock(procPtr);
  775.     if (procPtr->genFlags & PROC_MIG_ERROR) {
  776.     Proc_Unlock(procPtr);
  777.     goto failure;
  778.     }
  779.     Proc_Unlock(procPtr);
  780.     
  781.     if (foreign) {
  782.     PROC_MIG_DEC_STAT(foreign);
  783.     if (evicting ||
  784.         (proc_MigStats.foreign == 0 &&
  785.          proc_MigStats.evictionsInProgress != 0)) {
  786.         ProcMigEvictionComplete();
  787.     }
  788. #ifndef CLEAN
  789.     if (proc_MigDoStats) {
  790.         if (!evicting) {
  791.         PROC_MIG_INC_STAT(migrationsHome);
  792.         }
  793.     }
  794. #endif /* CLEAN */
  795.     ProcExitProcess(procPtr, -1, -1, -1, TRUE);
  796.     } else {
  797. #ifndef CLEAN
  798.     if (proc_MigDoStats) {
  799.         PROC_MIG_INC_STAT(remote);
  800.         PROC_MIG_INC_STAT(exports);
  801.         if (exec) {
  802.         PROC_MIG_INC_STAT(execs);
  803.         }
  804.         PROC_MIG_INC_STAT(hostCounts[hostID]);
  805.     }
  806. #endif /* CLEAN */
  807.     Sched_ContextSwitch(PROC_MIGRATED);
  808.     }
  809.     panic("Proc_MigrateTrap: returned from context switch.\n");
  810.     return;
  811.  
  812.  failure:
  813.     /*
  814.      * If the process hit some error, like the other host rebooting or
  815.      * exiting on the other host, we don't bother sending an RPC to the
  816.      * other host.
  817.      */
  818.     Proc_Lock(procPtr);
  819.     if (!(procPtr->genFlags & PROC_MIG_ERROR)) {
  820.     ProcMigKillRemoteCopy((ClientData) procPtr->peerProcessID,
  821.         (Proc_CallInfo *) NIL);
  822.     }
  823.     procPtr->genFlags &= ~(PROC_MIGRATING|PROC_REMOTE_EXEC_PENDING|
  824.                PROC_MIG_ERROR);
  825.     procPtr->migFlags &= ~PROC_EVICTING;
  826.     ProcMigWakeupWaiters();
  827.     if (proc_DoTrace && proc_MigDebugLevel > 0 && !foreign) {
  828.     record.processID = pid;
  829.     record.flags = PROC_MIGTRACE_HOME;
  830.     record.info.filler = NIL;
  831.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_END_MIG,
  832.              (ClientData) &record);
  833.     }
  834. #ifndef CLEAN
  835.     if (proc_MigDoStats) {
  836.     PROC_MIG_INC_STAT(errors);
  837.     }
  838. #endif /* CLEAN */
  839.     /*
  840.      * The migration failed, so exit.  By calling the exit routine
  841.      * directly we avoid problems that might result from having no
  842.      * VM, etc.
  843.      */
  844.     Proc_Unlock(procPtr);
  845.     Proc_ExitInt(PROC_TERM_DESTROYED, (int) PROC_NO_PEER, 0);
  846. }
  847.  
  848. /*
  849.  *----------------------------------------------------------------------
  850.  *
  851.  * AbortMigration --
  852.  *
  853.  *    Undo a migration at a point when the process can still be
  854.  *    continued on the local host.  This is only true when migrating
  855.  *    a running process, not when execing a new image, since we can't
  856.  *    recover from that.
  857.  *
  858.  * Results:
  859.  *    None.
  860.  *
  861.  * Side effects:
  862.  *    If the process is currently local, an RPC is sent to the remote host.
  863.  *
  864.  *----------------------------------------------------------------------
  865.  */
  866. static void
  867. AbortMigration(procPtr)
  868.     Proc_ControlBlock *procPtr; /* ptr to process control block */
  869. {
  870.     if (!(procPtr->genFlags & PROC_FOREIGN)) {
  871.     ProcMigKillRemoteCopy((ClientData) procPtr->peerProcessID,
  872.         (Proc_CallInfo *) NIL);
  873.     procPtr->peerProcessID = NIL;
  874.     procPtr->peerHostID = NIL;
  875.     }
  876.     procPtr->genFlags &= ~PROC_MIGRATING;
  877.     procPtr->sigPendingMask &= ~(1 << SIG_MIGRATE_TRAP);
  878.     Proc_Unlock(procPtr);
  879.     ProcMigWakeupWaiters();
  880. }
  881.  
  882. /*
  883.  *----------------------------------------------------------------------
  884.  *
  885.  * ProcMigReceiveProcess --
  886.  *
  887.  *    Receive the encapsulated state of a process from another host
  888.  *    and deencapsulate it by calling the appropriate callback routines.
  889.  *    If deencapsulation succeeds, resume the migrated process.
  890.  *
  891.  * Results:
  892.  *    A ReturnStatus indicates whether deencapsulation succeeds.  If
  893.  *     a module returns an error, the first error is returned and the
  894.  *    rest of the state is not deencapsulated.
  895.  *
  896.  * Side effects:
  897.  *    The process is resumed on this host.
  898.  *
  899.  *----------------------------------------------------------------------
  900.  */
  901.  
  902. /* ARGSUSED */
  903. ReturnStatus
  904. ProcMigReceiveProcess(cmdPtr, procPtr, inBufPtr, outBufPtr)
  905.     ProcMigCmd *cmdPtr;/* contains ID of process on this host */
  906.     Proc_ControlBlock *procPtr; /* ptr to process control block */
  907.     Proc_MigBuffer *inBufPtr;    /* input buffer */
  908.     Proc_MigBuffer *outBufPtr;    /* output buffer (stays NIL) */
  909. {
  910.     ReturnStatus status = SUCCESS;
  911.     Address bufPtr;
  912.     register int i;
  913.     Proc_EncapInfo *infoPtr;
  914.  
  915.     Proc_Lock(procPtr);
  916.     procPtr->genFlags = (procPtr->genFlags | PROC_MIGRATING) &
  917.     ~PROC_MIGRATION_DONE;
  918.  
  919.     /*
  920.      * Go through the buffer to deencapsulate the process module-by-module.
  921.      */
  922.     bufPtr = inBufPtr->ptr;
  923.     for (i = 0; i < PROC_MIG_NUM_CALLBACKS; i++) {
  924.     infoPtr = (Proc_EncapInfo *) bufPtr;
  925.     if (infoPtr->token != encapCallbacks[i].token) {
  926.         /*
  927.          * This callback wasn't used.
  928.          */
  929.         continue;
  930.     }
  931.     if (infoPtr->special) {
  932.         /*
  933.          * This is where we'd like to handle special cases like shared
  934.          * memory processes.  For now, this should never happen.
  935.          */
  936.         if (proc_MigDebugLevel > 0) {
  937.         panic("ProcMigReceiveProcess: special flag set?! (continuable -- but call Fred)");
  938.         }
  939.         procPtr->genFlags &= ~PROC_MIGRATING;
  940.         Proc_Unlock(procPtr);
  941.         return(PROC_MIGRATION_REFUSED);
  942.     }
  943.     if (proc_MigDebugLevel > 5) {
  944.         printf("Calling deencapFunc %d\n", i);
  945.     }
  946.     bufPtr += sizeof(Proc_EncapInfo);
  947.     status = (*encapCallbacks[i].deencapFunc)(procPtr, infoPtr, bufPtr);
  948. #ifdef lint
  949.     status = DeencapProcState(procPtr, infoPtr, bufPtr);
  950.     status = ProcExecDeencapState(procPtr, infoPtr, bufPtr);
  951.     status = Vm_DeencapState(procPtr, infoPtr, bufPtr);
  952.     status = Fs_DeencapFileState(procPtr, infoPtr, bufPtr);
  953.     status = Mach_DeencapState(procPtr, infoPtr, bufPtr);
  954.     status = Prof_DeencapState(procPtr, infoPtr, bufPtr);
  955.     status = Sig_DeencapState(procPtr, infoPtr, bufPtr);
  956. #endif /* lint */
  957.     if (status != SUCCESS) {
  958.         printf("Warning: ProcMigReceiveProcess: error returned by deencapsulation procedure %s:\n\t%s.\n",
  959. #ifdef BREAKS_KDBX
  960.            callbackNames[i].deencapFunc,
  961. #else /* BREAKS_KDBX */
  962.            "(can't get name)", 
  963. #endif /* BREAKS_KDBX */
  964.            Stat_GetMsg(status));
  965.         procPtr->genFlags &= ~PROC_MIGRATING;
  966.         Proc_Unlock(procPtr);
  967.         return(status);
  968.     }
  969.     bufPtr += infoPtr->size;
  970.     }
  971.  
  972.     /*
  973.      * Update statistics.
  974.      */
  975.     if (procPtr->genFlags & PROC_FOREIGN) {
  976.     PROC_MIG_INC_STAT(foreign);
  977. #ifndef CLEAN
  978.     if (proc_MigDoStats) {
  979.         PROC_MIG_INC_STAT(imports);
  980.     }
  981. #endif /* CLEAN */
  982.     } else {
  983. #ifndef CLEAN
  984.     if (proc_MigDoStats) {
  985.         PROC_MIG_INC_STAT(returns);
  986.         PROC_MIG_DEC_STAT(remote);
  987.     }
  988. #endif /* CLEAN */
  989.     }
  990.  
  991.     procPtr->genFlags &= ~PROC_MIGRATING;
  992.     Proc_Unlock(procPtr);
  993.  
  994.     return(status);
  995. }
  996.  
  997.  
  998.  
  999. /*
  1000.  * Define the process state that is sent during migration.
  1001.  * See proc.h for explanations of these fields.
  1002.  * This structure is followed by a variable-length string containing
  1003.  * procPtr->argString, padded to an integer boundary.
  1004.  */
  1005. typedef struct {
  1006.     int            migFlags;
  1007.     Proc_PID        parentID;
  1008.     int            familyID;
  1009.     int            userID;
  1010.     int            effectiveUserID;
  1011.     int            genFlags;
  1012.     int            syncFlags;
  1013.     int            schedFlags;
  1014.     int            exitFlags;
  1015.     int         billingRate;
  1016.     unsigned int     recentUsage;
  1017.     unsigned int     weightedUsage;
  1018.     unsigned int     unweightedUsage;
  1019.     Proc_Time        kernelCpuUsage;
  1020.     Proc_Time        userCpuUsage;
  1021.     Proc_Time        childKernelCpuUsage;
  1022.     Proc_Time        childUserCpuUsage;
  1023.     int         numQuantumEnds;
  1024.     int            numWaitEvents;
  1025.     unsigned int     schedQuantumTicks;
  1026.     Proc_TimerInterval  timers[PROC_MAX_TIMER + 1];
  1027.     int            argStringLength;
  1028.     int            unixProgress;
  1029. } EncapState;
  1030.  
  1031. #define COPY_STATE(from, to, field) to->field = from->field
  1032.  
  1033. /*
  1034.  * A process is allowed to update its userID, effectiveUserID,
  1035.  * billingRate, or familyID.  If any of these fields is modified, all
  1036.  * of them are transferred to the remote host.
  1037.  */
  1038.  
  1039. typedef struct {
  1040.     int            familyID;
  1041.     int            userID;
  1042.     int            effectiveUserID;
  1043.     int         billingRate;
  1044. } UpdateEncapState;
  1045.  
  1046. /*
  1047.  * Parameters for a remote Proc_Suspend or resume.
  1048.  */
  1049.  
  1050. typedef struct {
  1051.     int        termReason; /* Reason why process went to this state.*/
  1052.     int        termStatus; /* Termination status.*/
  1053.     int        termCode;   /* Termination code. */
  1054.     int        flags;        /* Exit flags. */
  1055. } SuspendInfo;
  1056.  
  1057. /*
  1058.  * Extra info used for suspend callback.
  1059.  */
  1060.  
  1061. typedef struct {
  1062.     Proc_PID    processID;    /* Process being suspended/resumed. */
  1063.     SuspendInfo info;        /* Info to pass to home machine. */
  1064. } SuspendCallbackInfo;
  1065.  
  1066. /*
  1067.  *----------------------------------------------------------------------
  1068.  *
  1069.  * GetProcEncapSize --
  1070.  *
  1071.  *    Determine the size of the encapsulated process state.
  1072.  *
  1073.  * Results:
  1074.  *    SUCCESS is returned directly; the size of the encapsulated state
  1075.  *    is returned in infoPtr->size.
  1076.  *
  1077.  * Side effects:
  1078.  *    None.
  1079.  *
  1080.  *----------------------------------------------------------------------
  1081.  */
  1082.  
  1083. /* ARGSUSED */
  1084. static ReturnStatus
  1085. GetProcEncapSize(procPtr, hostID, infoPtr)
  1086.     Proc_ControlBlock *procPtr;            /* process being migrated */
  1087.     int hostID;                    /* host to which it migrates */
  1088.     Proc_EncapInfo *infoPtr;            /* area w/ information about
  1089.                          * encapsulated state */
  1090. {
  1091.     infoPtr->size = sizeof(EncapState) +
  1092.     Byte_AlignAddr(strlen(procPtr->argString) + 1);
  1093.     /*
  1094.      * The clientData part of the EncapInfo struct is used to indicate
  1095.      * that the process is migrating home.
  1096.      */
  1097.     if (procPtr->genFlags & PROC_FOREIGN) {
  1098.     infoPtr->data = (ClientData) 1;
  1099.     if (proc_MigDebugLevel > 4) {
  1100.         printf("Encapsulating foreign process %x.\n", procPtr->processID);
  1101.     }
  1102.     } else {
  1103.     infoPtr->data = (ClientData) 0;
  1104.     if (proc_MigDebugLevel > 4) {
  1105.         printf("Encapsulating local process %x.\n", procPtr->processID);
  1106.     }
  1107.     }
  1108.  
  1109.     return(SUCCESS);    
  1110. }
  1111.  
  1112.  
  1113. /*
  1114.  *----------------------------------------------------------------------
  1115.  *
  1116.  * EncapProcState --
  1117.  *
  1118.  *    Encapsulate the state of a process from the Proc_ControlBlock
  1119.  *    and return it in the buffer provided.
  1120.  *
  1121.  * Results:
  1122.  *    SUCCESS.  The buffer is filled.
  1123.  *
  1124.  * Side effects:
  1125.  *    None.
  1126.  *----------------------------------------------------------------------
  1127.  */
  1128.  
  1129. /* ARGSUSED */
  1130. static ReturnStatus
  1131. EncapProcState(procPtr, hostID, infoPtr, bufPtr)
  1132.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  1133.     int hostID;                  /* host to which it migrates */
  1134.     Proc_EncapInfo *infoPtr;
  1135.     Address bufPtr;
  1136. {
  1137.     int argStringLength;
  1138.     EncapState *encapPtr = (EncapState *) bufPtr;
  1139.     int i;
  1140.     ReturnStatus status;
  1141.     Proc_TimerInterval timer;
  1142.  
  1143.     if (procPtr->locksHeld != 0) {
  1144.     panic("Migrating a process that's holding a lock.\n");
  1145.     }
  1146.  
  1147.     COPY_STATE(procPtr, encapPtr, migFlags);
  1148.     COPY_STATE(procPtr, encapPtr, parentID);
  1149.     COPY_STATE(procPtr, encapPtr, familyID);
  1150.     COPY_STATE(procPtr, encapPtr, userID);
  1151.     COPY_STATE(procPtr, encapPtr, effectiveUserID);
  1152.     COPY_STATE(procPtr, encapPtr, genFlags);
  1153.     COPY_STATE(procPtr, encapPtr, syncFlags);
  1154.     COPY_STATE(procPtr, encapPtr, schedFlags);
  1155.     COPY_STATE(procPtr, encapPtr, exitFlags);
  1156.     COPY_STATE(procPtr, encapPtr, billingRate);
  1157.     COPY_STATE(procPtr, encapPtr, recentUsage);
  1158.     COPY_STATE(procPtr, encapPtr, weightedUsage);
  1159.     COPY_STATE(procPtr, encapPtr, unweightedUsage);
  1160.     COPY_STATE(procPtr, encapPtr, kernelCpuUsage);
  1161.     COPY_STATE(procPtr, encapPtr, userCpuUsage);
  1162.     COPY_STATE(procPtr, encapPtr, childKernelCpuUsage);
  1163.     COPY_STATE(procPtr, encapPtr, childUserCpuUsage);
  1164.     COPY_STATE(procPtr, encapPtr, numQuantumEnds);
  1165.     COPY_STATE(procPtr, encapPtr, numWaitEvents);
  1166.     COPY_STATE(procPtr, encapPtr, schedQuantumTicks);
  1167.     COPY_STATE(procPtr, encapPtr, unixProgress);
  1168.  
  1169.  
  1170.     /*
  1171.      * Get the timer state in an easy-to-transfer form.  Unlock
  1172.      * the process first since ProcChangeTimer will lock it.
  1173.      */
  1174.     timer.interval = time_ZeroSeconds;
  1175.     timer.curValue = time_ZeroSeconds;
  1176.     
  1177.     Proc_Unlock(procPtr);
  1178.     for (i = 0; i <= PROC_MAX_TIMER; i++) {
  1179.     status = ProcChangeTimer(i, &timer, &encapPtr->timers[i], FALSE);
  1180. #define DEBUG_TIMER
  1181. #ifdef DEBUG_TIMER
  1182.     if ((encapPtr->timers[i].curValue.seconds < 0) || 
  1183.         (encapPtr->timers[i].curValue.microseconds < 0) ||
  1184.         (encapPtr->timers[i].curValue.microseconds > ONE_SECOND) ||
  1185.         (encapPtr->timers[i].interval.seconds < 0) || 
  1186.         (encapPtr->timers[i].interval.microseconds < 0) ||
  1187.         (encapPtr->timers[i].interval.microseconds > ONE_SECOND)) {
  1188.         panic("Migration error: timer value (<%d,%d>@<%d,%d>)  is bad.\n",
  1189.           encapPtr->timers[i].curValue.seconds,
  1190.           encapPtr->timers[i].curValue.microseconds,
  1191.           encapPtr->timers[i].interval.seconds,
  1192.           encapPtr->timers[i].interval.microseconds);
  1193.         Proc_Lock(procPtr);
  1194.         return(FAILURE);
  1195.     }
  1196. #endif /* DEBUG_TIMER */
  1197.  
  1198.     if (status != SUCCESS) {
  1199.         if (proc_MigDebugLevel > 0) {
  1200.         printf("EncapProcState: error returned from ProcChangeTimer: %s.\n",
  1201.                Stat_GetMsg(status));
  1202.         }
  1203.         Proc_Lock(procPtr);
  1204.         return(status);
  1205.     }
  1206.     }
  1207.     Proc_Lock(procPtr);
  1208.  
  1209.     bufPtr += sizeof(EncapState);
  1210.     argStringLength = Byte_AlignAddr(strlen(procPtr->argString) + 1);
  1211.     encapPtr->argStringLength = argStringLength;
  1212.     (void) strncpy(bufPtr, procPtr->argString, argStringLength);
  1213.  
  1214.  
  1215.     /*
  1216.      * If we're migrating away from home, subtract the process's current
  1217.      * CPU usage so it can be added in again when the process returns
  1218.      * here.  Passing negative tick values seems like a relatively easy
  1219.      * way to subtract time, though perhaps we should pass a separate parameter
  1220.      * to ProcRecordUsage instead and call Timer_AddTicks or
  1221.      * Timer_SubtractTicks depending on the parameter.
  1222.      */
  1223. #ifndef CLEAN
  1224.     if (infoPtr->data == 0) {
  1225.     Timer_Ticks ticks;
  1226.     Timer_SubtractTicks(timer_TicksZeroSeconds,
  1227.                 procPtr->kernelCpuUsage.ticks,
  1228.                 &ticks);
  1229.     Timer_SubtractTicks(ticks, procPtr->userCpuUsage.ticks,
  1230.                 &ticks);
  1231.     ProcRecordUsage(ticks, PROC_MIG_USAGE_REMOTE_CPU);
  1232.     }
  1233. #endif /* CLEAN */
  1234.     return(SUCCESS);
  1235. }
  1236.  
  1237.  
  1238. /*
  1239.  *----------------------------------------------------------------------
  1240.  *
  1241.  * DeencapProcState --
  1242.  *
  1243.  *    Get information from a Proc_ControlBlock from another host.
  1244.  *    The information is contained in the parameter ``buffer''.
  1245.  *    The process control block should be locked on entry and exit.
  1246.  *
  1247.  * Results:
  1248.  *    Usually SUCCESS.  Can propagate an error return from 
  1249.  *    ProcChangeTimer.  Returns PROC_MIGRATION_REFUSED if the 
  1250.  *    process has been flagged as unmigratable and this is not its
  1251.  *    home node.
  1252.  *
  1253.  * Side effects:
  1254.  *    None.
  1255.  *----------------------------------------------------------------------
  1256.  */
  1257.  
  1258. /* ARGSUSED */
  1259. static ReturnStatus
  1260. DeencapProcState(procPtr, infoPtr, bufPtr)
  1261.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  1262.     Proc_EncapInfo *infoPtr;          /* information about the buffer */
  1263.     Address bufPtr;              /* buffer containing data */
  1264. {
  1265.     Boolean         home;
  1266.     EncapState *encapPtr = (EncapState *) bufPtr;
  1267.     int i;
  1268.     ReturnStatus status;
  1269.     Timer_Ticks ticks;
  1270.     
  1271.     if (infoPtr->data == 0) {
  1272.     if (proc_MigDebugLevel > 4) {
  1273.         printf("Deencapsulating foreign process %x.\n", procPtr->processID);
  1274.     }
  1275.     home = FALSE;
  1276.     } else {
  1277.     if (proc_MigDebugLevel > 4) {
  1278.         printf("Deencapsulating local process %x.\n", procPtr->processID);
  1279.     }
  1280.     home = TRUE;
  1281.     }
  1282.  
  1283.  
  1284.     COPY_STATE(encapPtr, procPtr, migFlags);
  1285.     COPY_STATE(encapPtr, procPtr, parentID);
  1286.     COPY_STATE(encapPtr, procPtr, familyID);
  1287.     COPY_STATE(encapPtr, procPtr, userID);
  1288.     COPY_STATE(encapPtr, procPtr, effectiveUserID);
  1289.     COPY_STATE(encapPtr, procPtr, genFlags);
  1290.     COPY_STATE(encapPtr, procPtr, syncFlags);
  1291.     COPY_STATE(encapPtr, procPtr, schedFlags);
  1292.     COPY_STATE(encapPtr, procPtr, exitFlags);
  1293.     COPY_STATE(encapPtr, procPtr, billingRate);
  1294.     COPY_STATE(encapPtr, procPtr, recentUsage);
  1295.     COPY_STATE(encapPtr, procPtr, weightedUsage);
  1296.     COPY_STATE(encapPtr, procPtr, unweightedUsage);
  1297.     COPY_STATE(encapPtr, procPtr, kernelCpuUsage);
  1298.     COPY_STATE(encapPtr, procPtr, userCpuUsage);
  1299.     COPY_STATE(encapPtr, procPtr, childKernelCpuUsage);
  1300.     COPY_STATE(encapPtr, procPtr, childUserCpuUsage);
  1301.     COPY_STATE(encapPtr, procPtr, numQuantumEnds);
  1302.     COPY_STATE(encapPtr, procPtr, numWaitEvents);
  1303.     COPY_STATE(encapPtr, procPtr, schedQuantumTicks);
  1304.     COPY_STATE(encapPtr, procPtr, unixProgress);
  1305.  
  1306.     /* 
  1307.      * The process should never be flagged as unmigratable, so 
  1308.      * complain if it is.  Allow "unmigratable" processes to migrate 
  1309.      * back to the home node, but don't let them go anywhere else.
  1310.      */
  1311.     if (procPtr->genFlags & PROC_DONT_MIGRATE) {
  1312.     Sys_HostPrint(procPtr->peerHostID,
  1313.               "wants to give us an unmigratable process.\n");
  1314.     if (!home) {
  1315.         return PROC_MIGRATION_REFUSED;
  1316.     }
  1317.     }
  1318.  
  1319.     /*
  1320.      * Set the effective process for this processor while doing the
  1321.      * ProcChangeTimer since we're doing it on behalf of another
  1322.      * process.
  1323.      */
  1324.  
  1325.     Proc_SetEffectiveProc(procPtr);
  1326.  
  1327.     Proc_Unlock(procPtr);
  1328.     for (i = 0; i <= PROC_MAX_TIMER; i++) {
  1329.     status = ProcChangeTimer(i, &encapPtr->timers[i],
  1330.                  (Proc_TimerInterval *) USER_NIL, FALSE);
  1331.     if (status != SUCCESS) {
  1332.         if (proc_MigDebugLevel > 0) {
  1333.         printf("DeencapProcState: error returned from ProcChangeTimer: %s.\n",
  1334.                Stat_GetMsg(status));
  1335.         }
  1336.         Proc_Lock(procPtr);
  1337.         return(status);
  1338.     }
  1339.     }
  1340.     Proc_Lock(procPtr);
  1341.  
  1342.     Proc_SetEffectiveProc((Proc_ControlBlock *) NIL);
  1343.  
  1344.     bufPtr += sizeof(*encapPtr);
  1345.     if (procPtr->argString != (char *) NIL) {
  1346.     free(procPtr->argString);
  1347.     }
  1348.     procPtr->argString = (char *) malloc(encapPtr->argStringLength);
  1349.     bcopy(bufPtr, (Address) procPtr->argString, encapPtr->argStringLength);
  1350.  
  1351.     procPtr->genFlags |= PROC_NO_VM;
  1352.     if (home) {
  1353.     procPtr->genFlags &= (~PROC_FOREIGN);
  1354.     procPtr->kcallTable = mach_NormalHandlers;
  1355.     } else {
  1356.     procPtr->genFlags |= PROC_FOREIGN;
  1357.     procPtr->kcallTable = mach_MigratedHandlers;
  1358.     }
  1359.     procPtr->genFlags &= ~PROC_MIG_PENDING;
  1360.     procPtr->schedFlags &=
  1361.     ~(SCHED_STACK_IN_USE | SCHED_CONTEXT_SWITCH_PENDING);
  1362.  
  1363.     /*
  1364.      * Initialize some of the fields as if for a new process.  If migrating
  1365.      * home, these are already set up.   Fix up dependencies.
  1366.      */
  1367.     procPtr->state         = PROC_NEW;
  1368.     Vm_ProcInit(procPtr);
  1369.     procPtr->event            = NIL;
  1370.  
  1371.     if (!home) {
  1372.     /*
  1373.      *  Initialize our child list to remove any old links.
  1374.      */
  1375.     List_Init((List_Links *) procPtr->childList);
  1376.  
  1377.     } else {
  1378.     /*
  1379.      * Forget the dependency on the other host; we're running
  1380.      * locally now.
  1381.      */
  1382.     ProcMigRemoveDependency(procPtr->processID, TRUE);
  1383.     /*
  1384.      * Update remote CPU usage stats.
  1385.      */
  1386. #ifndef CLEAN
  1387.     Timer_AddTicks(procPtr->kernelCpuUsage.ticks,
  1388.             procPtr->userCpuUsage.ticks, &ticks);
  1389.     ProcRecordUsage(ticks, PROC_MIG_USAGE_REMOTE_CPU);
  1390. #endif /* CLEAN */
  1391.     if (procPtr->migFlags & PROC_EVICTING) {
  1392.         procPtr->migFlags &= ~PROC_EVICTING;
  1393. #ifndef CLEAN
  1394.         if (!(procPtr->migFlags & PROC_WAS_EVICTED)) {
  1395.         procPtr->migFlags |= PROC_WAS_EVICTED;
  1396.         procPtr->preEvictionUsage.ticks = ticks;
  1397.         }
  1398. #endif /* CLEAN */
  1399.     } else if (!home) {
  1400.         procPtr->migFlags &= ~PROC_WAS_EVICTED;
  1401.     }
  1402.     }
  1403.  
  1404.  
  1405.     if (proc_MigDebugLevel > 4) {
  1406.     printf("Received process state for process %x.\n", procPtr->processID);
  1407.     }
  1408.  
  1409.     return(SUCCESS);
  1410. }
  1411.  
  1412.  
  1413. /*
  1414.  *----------------------------------------------------------------------
  1415.  *
  1416.  * Proc_MigUpdateInfo --
  1417.  *
  1418.  *    Send the updateable portions of the state of a process to the
  1419.  *    host on which it is currently executing.  This requires
  1420.  *    packaging the relevant information from the Proc_ControlBlock
  1421.  *    and sending it via an RPC.
  1422.  *
  1423.  *     The process is assumed to be locked.
  1424.  *
  1425.  * Results:
  1426.  *    A ReturnStatus is returned to indicate the status of the RPC.
  1427.  *
  1428.  * Side effects:
  1429.  *    A remote procedure call is performed and the process state
  1430.  *    is transferred.
  1431.  *
  1432.  *----------------------------------------------------------------------
  1433.  */
  1434.  
  1435. ReturnStatus
  1436. Proc_MigUpdateInfo(procPtr)
  1437.     Proc_ControlBlock     *procPtr; /* The migrated process */
  1438. {
  1439.     ReturnStatus status;
  1440.     ProcMigCmd cmd;
  1441.     UpdateEncapState state;
  1442.     UpdateEncapState *statePtr = &state;
  1443.     Proc_MigBuffer inBuf;
  1444.  
  1445.     COPY_STATE(procPtr, statePtr, familyID);
  1446.     COPY_STATE(procPtr, statePtr, userID);
  1447.     COPY_STATE(procPtr, statePtr, effectiveUserID);
  1448.     COPY_STATE(procPtr, statePtr, billingRate);
  1449.  
  1450.     /*
  1451.      * Set up for the RPC.
  1452.      */
  1453.     cmd.command = PROC_MIGRATE_CMD_UPDATE;
  1454.     cmd.remotePid = procPtr->peerProcessID;
  1455.     inBuf.size = sizeof(UpdateEncapState);
  1456.     inBuf.ptr = (Address) statePtr;
  1457.  
  1458.     status = ProcMigCommand(procPtr->peerHostID, &cmd, &inBuf,
  1459.                 (Proc_MigBuffer *) NIL);
  1460.  
  1461.     if (status != SUCCESS && proc_MigDebugLevel > 0) {
  1462.     printf("Warning: Proc_MigUpdateInfo: error returned updating information on host %d:\n\t%s.\n",
  1463.         procPtr->peerHostID,Stat_GetMsg(status));
  1464.     }
  1465.     return(status);
  1466. }
  1467.  
  1468.  
  1469. /*
  1470.  *----------------------------------------------------------------------
  1471.  *
  1472.  * ProcMigGetUpdate --
  1473.  *
  1474.  *    Receive the updateable portions of the state of a process from its
  1475.  *    home node.
  1476.  *
  1477.  * Results:
  1478.  *    SUCCESS.
  1479.  *
  1480.  * Side effects:
  1481.  *    The process's control block is locked and then updated.
  1482.  *
  1483.  *----------------------------------------------------------------------
  1484.  */
  1485.  
  1486. /* ARGSUSED */
  1487. ReturnStatus
  1488. ProcMigGetUpdate(cmdPtr, procPtr, inBufPtr, outBufPtr)
  1489.     ProcMigCmd *cmdPtr;/* contains ID of process on this host */
  1490.     Proc_ControlBlock *procPtr; /* ptr to process control block */
  1491.     Proc_MigBuffer *inBufPtr;    /* input buffer */
  1492.     Proc_MigBuffer *outBufPtr;    /* output buffer (stays NIL) */
  1493. {
  1494.     UpdateEncapState *statePtr = (UpdateEncapState *) inBufPtr->ptr;
  1495.  
  1496.     Proc_Lock(procPtr);
  1497.     COPY_STATE(statePtr, procPtr, familyID);
  1498.     COPY_STATE(statePtr, procPtr, userID);
  1499.     COPY_STATE(statePtr, procPtr, effectiveUserID);
  1500.     COPY_STATE(statePtr, procPtr, billingRate);
  1501.     Proc_Unlock(procPtr);
  1502.     return(SUCCESS);
  1503.  
  1504. }
  1505.  
  1506.  
  1507. /*
  1508.  *----------------------------------------------------------------------
  1509.  *
  1510.  * ProcRemoteSuspend --
  1511.  *
  1512.  *    Tell the home node of a process that it has been suspended or resumed.
  1513.  *    This routine is called from within the signal handling routines.
  1514.  *
  1515.  * Results:
  1516.  *    None.
  1517.  *
  1518.  * Side effects:
  1519.  *    Sets up a background process to make an RPC.
  1520.  *
  1521.  *----------------------------------------------------------------------
  1522.  */
  1523.  
  1524. void
  1525. ProcRemoteSuspend(procPtr, exitFlags)
  1526.     register Proc_ControlBlock     *procPtr;  /* Process whose state is changing. */
  1527.     int exitFlags;               /* Flags to set for child. */
  1528. {
  1529.     ReturnStatus status;
  1530.     SuspendCallbackInfo *callPtr;         /* Information for the callback. */
  1531.     SuspendInfo *infoPtr;         /* Info to pass back. */
  1532.  
  1533.     if (proc_MigDebugLevel > 4) {
  1534.     printf("ProcRemoteSuspend(%x) called.\n", procPtr->processID);
  1535.     }
  1536.  
  1537.     status = Recov_IsHostDown(procPtr->peerHostID);
  1538.     if (status != SUCCESS) {
  1539.     if (proc_MigDebugLevel > 0) {
  1540.         printf("ProcRemoteSuspend: host %d is down; killing process %x.\n",
  1541.                procPtr->peerHostID, procPtr->processID);
  1542.     }
  1543.     /*
  1544.      * Perform an exit on behalf of the process -- it's not
  1545.      * in a state where we can signal it.  The process is
  1546.          * unlocked as a side effect.
  1547.      */
  1548.     ProcExitProcess(procPtr, PROC_TERM_DESTROYED, (int) PROC_NO_PEER, 0,
  1549.             FALSE);
  1550.     /*
  1551.      * This point should not be reached, but the N-O-T-R-E-A-C-H-E-D
  1552.      * directive causes a complaint when there's code after it.
  1553.      */
  1554.     panic("ProcRemoteSuspend: Proc_ExitInt returned.\n");
  1555.     return;
  1556.     }
  1557.  
  1558.     callPtr = (SuspendCallbackInfo *) malloc(sizeof(SuspendCallbackInfo));
  1559.     infoPtr = &callPtr->info;
  1560.     callPtr->processID = procPtr->processID;
  1561.  
  1562.     COPY_STATE(procPtr, infoPtr, termReason);
  1563.     COPY_STATE(procPtr, infoPtr, termStatus);
  1564.     COPY_STATE(procPtr, infoPtr, termCode);
  1565.     infoPtr->flags = exitFlags;
  1566.     Proc_CallFunc(SuspendCallback, (ClientData) callPtr, 0);
  1567.     
  1568. }
  1569.  
  1570.  
  1571. /*
  1572.  *----------------------------------------------------------------------
  1573.  *
  1574.  * SuspendCallback --
  1575.  *
  1576.  *    Tell the home node of a process that it has been suspended or resumed.
  1577.  *    This is called via a Proc_CallFunc so the signal monitor lock
  1578.  *    is not held.
  1579.  *
  1580.  * Results:
  1581.  *    None.
  1582.  *
  1583.  * Side effects:
  1584.  *    A remote procedure call is performed.
  1585.  *
  1586.  *----------------------------------------------------------------------
  1587.  */
  1588.  
  1589. /* ARGSUSED */
  1590. static void
  1591. SuspendCallback(data, callInfoPtr)
  1592.     ClientData        data;
  1593.     Proc_CallInfo    *callInfoPtr;        /* not used */
  1594. {
  1595.     SuspendCallbackInfo *callPtr;    /* Pointer to callback info. */
  1596.     register Proc_ControlBlock     *procPtr;  /* Process whose state is changing. */
  1597.     ReturnStatus status;
  1598.     int numTries;            /* number of times trying RPC */
  1599.     ProcMigCmd cmd;
  1600.     Proc_MigBuffer inBuf;
  1601.     int host = 0;
  1602.  
  1603.     callPtr = (SuspendCallbackInfo *) data;
  1604.     if (proc_MigDebugLevel > 4) {
  1605.     printf("SuspendCallback(%x) called.\n", callPtr->processID);
  1606.     }
  1607.     procPtr = Proc_LockPID(callPtr->processID);
  1608.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1609.     status = PROC_NO_PEER;
  1610.     goto done;
  1611.     }
  1612.     host = procPtr->peerHostID;
  1613.     cmd.remotePid = procPtr->peerProcessID;
  1614.  
  1615.     /*
  1616.      * Now that we have the relevant info, unlock the process while we're
  1617.      * doing the RPC.  We don't need it anymore anyway.
  1618.      */
  1619.  
  1620.     Proc_Unlock(procPtr);
  1621.  
  1622.     /*
  1623.      * Set up for the RPC.
  1624.      */
  1625.     cmd.command = PROC_MIGRATE_CMD_SUSPEND;
  1626.  
  1627.     inBuf.size = sizeof(SuspendInfo);
  1628.     inBuf.ptr = (Address) &callPtr->info;
  1629.  
  1630.     for (numTries = 0; numTries < PROC_MAX_RPC_RETRIES; numTries++) {
  1631.     status = ProcMigCommand(host, &cmd, &inBuf,
  1632.                 (Proc_MigBuffer *) NIL);
  1633.     if (status != RPC_TIMEOUT) {
  1634.         break;
  1635.     }
  1636.     status = Proc_WaitForHost(host);
  1637.     if (status != SUCCESS) {
  1638.         break;
  1639.     }
  1640.     }
  1641.     done:
  1642.     if (status != SUCCESS && proc_MigDebugLevel > 2) {
  1643.     printf("Warning: SuspendCallback: error returned passing suspend to host %d:\n\t%s.\n",
  1644.         host,Stat_GetMsg(status));
  1645.     } else if (proc_MigDebugLevel > 4) {
  1646.     printf("SuspendCallback(%x) completed successfully.\n",
  1647.            callPtr->processID);
  1648.     }
  1649.     free ((Address) callPtr);
  1650. }
  1651.  
  1652.  
  1653. /*
  1654.  *----------------------------------------------------------------------
  1655.  *
  1656.  * ProcMigGetSuspend --
  1657.  *
  1658.  *    Receive the new exit status of a process from its remote node.
  1659.  *
  1660.  * Results:
  1661.  *    SUCCESS.
  1662.  *
  1663.  * Side effects:
  1664.  *    The process's control block is locked and then updated.
  1665.  *
  1666.  *----------------------------------------------------------------------
  1667.  */
  1668.  
  1669. /* ARGSUSED */
  1670. ReturnStatus
  1671. ProcMigGetSuspend(cmdPtr, procPtr, inBufPtr, outBufPtr)
  1672.     ProcMigCmd *cmdPtr;/* contains ID of process on this host */
  1673.     Proc_ControlBlock *procPtr; /* ptr to process control block */
  1674.     Proc_MigBuffer *inBufPtr;    /* input buffer */
  1675.     Proc_MigBuffer *outBufPtr;    /* output buffer (stays NIL) */
  1676. {
  1677.     register SuspendInfo *infoPtr = (SuspendInfo *) inBufPtr->ptr;
  1678.  
  1679.     Proc_Lock(procPtr);
  1680.  
  1681.     COPY_STATE(infoPtr, procPtr, termReason);
  1682.     COPY_STATE(infoPtr, procPtr, termStatus);
  1683.     COPY_STATE(infoPtr, procPtr, termCode);
  1684.  
  1685.     Proc_InformParent(procPtr, infoPtr->flags);
  1686.     Proc_Unlock(procPtr);
  1687.     return(SUCCESS);
  1688.  
  1689. }
  1690.  
  1691.  
  1692. /*
  1693.  *----------------------------------------------------------------------
  1694.  *
  1695.  * ProcMigEncapCallback --
  1696.  *
  1697.  *    Handle a callback on behalf of a module requesting more data.
  1698.  *    Not yet implemented.
  1699.  *
  1700.  * Results:
  1701.  *    A ReturnStatus, dependent on the module doing the callback.
  1702.  *
  1703.  * Side effects:
  1704.  *    Variable.
  1705.  *
  1706.  *----------------------------------------------------------------------
  1707.  */
  1708.  
  1709. /* ARGSUSED */
  1710. ReturnStatus
  1711. ProcMigEncapCallback(cmdPtr, procPtr, inBufPtr, outBufPtr)
  1712.     ProcMigCmd *cmdPtr;/* contains ID of process on this host */
  1713.     Proc_ControlBlock *procPtr; /* ptr to process control block */
  1714.     Proc_MigBuffer *inBufPtr;    /* input buffer */
  1715.     Proc_MigBuffer *outBufPtr;    /* output buffer (stays NIL) */
  1716. {
  1717.     return(FAILURE);
  1718. }
  1719.  
  1720.  
  1721. /*
  1722.  *----------------------------------------------------------------------
  1723.  *
  1724.  * ProcMigKillRemoteCopy --
  1725.  *
  1726.  *    Inform the remote host that a failure occurred during migration,
  1727.  *     so the incomplete process on the remote host will kill the process.
  1728.  *    This just sets up and issues a MigCommand.
  1729.  *
  1730.  * Results:
  1731.  *    None.  The caller doesn't normally care about the status of the
  1732.  *    RPC.
  1733.  *
  1734.  * Side effects:
  1735.  *    A remote procedure call is performed and the migrated process
  1736.  *    is killed.
  1737.  *
  1738.  *----------------------------------------------------------------------
  1739.  */
  1740.  
  1741. void
  1742. ProcMigKillRemoteCopy(data, infoPtr)
  1743.     ClientData        data;        /* The ID of the remote process */
  1744.     Proc_CallInfo    *infoPtr;    /* unused. */
  1745. {
  1746.     Proc_PID processID = (Proc_PID) data;
  1747.     ReturnStatus status;
  1748.     ProcMigCmd cmd;
  1749.     int hostID;                     /* Host to notify. */
  1750.  
  1751.     /*
  1752.      * Set up for the RPC.
  1753.      */
  1754.     cmd.command = PROC_MIGRATE_CMD_DESTROY;
  1755.     cmd.remotePid = processID;
  1756.     hostID = Proc_GetHostID(processID);
  1757.  
  1758.     status = ProcMigCommand(hostID, &cmd, (Proc_MigBuffer *) NIL,
  1759.                 (Proc_MigBuffer *) NIL);
  1760.  
  1761.     if (status != SUCCESS && proc_MigDebugLevel > 2) {
  1762.     printf("Warning: KillRemoteCopy: error returned by Rpc_Call: %s.\n",
  1763.         Stat_GetMsg(status));
  1764.     }
  1765. }
  1766.  
  1767.  
  1768.  
  1769. /*
  1770.  *----------------------------------------------------------------------
  1771.  *
  1772.  * Proc_FlagMigration --
  1773.  *
  1774.  *    Mark a process as waiting to migrate.  This will cause the process
  1775.  *    to trap to the Proc_MigrateTrap routine after the next time it
  1776.  *    traps into the kernel. 
  1777.  *
  1778.  *    The calling routine is assumed to hold the lock for the process.
  1779.  *
  1780.  * Results:
  1781.  *    None.
  1782.  *
  1783.  * Side effects:
  1784.  *    The process is flagged for migration.  If the process is suspended,
  1785.  *    it is resumed.
  1786.  *
  1787.  *----------------------------------------------------------------------
  1788.  */
  1789.  
  1790. void
  1791. Proc_FlagMigration(procPtr, hostID, exec)
  1792.     Proc_ControlBlock     *procPtr;    /* The process being migrated */
  1793.     int hostID;                /* Host to which it migrates */
  1794.     Boolean exec;            /* Whether it's doing a remote exec */
  1795. {
  1796.  
  1797.     procPtr->genFlags |= PROC_MIG_PENDING;
  1798.     procPtr->genFlags &= ~PROC_MIGRATION_DONE;
  1799.     if (exec) {
  1800.     /*
  1801.      * We flag the process specially so we know to copy over exec
  1802.      * arguments.  
  1803.      */
  1804.     procPtr->genFlags |= PROC_REMOTE_EXEC_PENDING;
  1805.     }
  1806.     procPtr->peerHostID = hostID;
  1807.     if (procPtr->state == PROC_SUSPENDED) {
  1808.     Sig_SendProc(procPtr, SIG_RESUME, 0, (Address)0);
  1809.     }
  1810.     Sig_SendProc(procPtr, SIG_MIGRATE_TRAP, 0, (Address)0);
  1811.     Sig_AllowMigration(procPtr);
  1812.  
  1813. }
  1814.  
  1815.  
  1816. /*
  1817.  *----------------------------------------------------------------------
  1818.  *
  1819.  * ProcInitiateMigration --
  1820.  *    
  1821.  *    Send a message to a specific workstation requesting permission to
  1822.  *    migrate a process.
  1823.  *
  1824.  * Results:
  1825.  *    SUCCESS is returned if permission is granted.
  1826.  *    PROC_MIGRATION_REFUSED is returned if the host is not accepting
  1827.  *        migrated processes or it is not at the right migration
  1828.  *        level.
  1829.  *    GEN_INVALID_ID if the user doesn't have permission to migrate
  1830.  *        from this host or to the other host.
  1831.  *    Other errors may be returned by the rpc module.
  1832.  *
  1833.  * Side effects:
  1834.  *    A message is sent to the remote workstation.
  1835.  *
  1836.  *----------------------------------------------------------------------
  1837.  */
  1838.  
  1839. ReturnStatus
  1840. ProcInitiateMigration(procPtr, hostID)
  1841.     register Proc_ControlBlock *procPtr;        /* process to migrate */
  1842.     int hostID;                          /* host to which to migrate */
  1843. {
  1844.     ReturnStatus status;
  1845.     ProcMigInitiateCmd init;
  1846.     ProcMigCmd cmd;
  1847.     Proc_MigBuffer inBuf;
  1848.     Proc_MigBuffer outBuf;
  1849.     Proc_PID pid;
  1850.     int foreign;
  1851.     
  1852.  
  1853.     init.processID = procPtr->processID;
  1854.     init.version = proc_MigrationVersion;
  1855.     init.userID = procPtr->userID;
  1856.     init.clientID = rpc_SpriteID;
  1857.     if (procPtr->genFlags & PROC_FOREIGN) {
  1858.     foreign = 1;
  1859.     cmd.remotePid = procPtr->peerProcessID;
  1860.     } else {
  1861.     foreign = 0;
  1862.     cmd.remotePid = (Proc_PID) NIL;
  1863.     }
  1864.     cmd.command = PROC_MIGRATE_CMD_INIT;
  1865.     
  1866.     inBuf.ptr = (Address) &init;
  1867.     inBuf.size = sizeof(ProcMigInitiateCmd);
  1868.  
  1869.     outBuf.ptr = (Address) &pid;
  1870.     outBuf.size = sizeof(Proc_PID);
  1871.  
  1872.     status = ProcMigCommand(hostID, &cmd, &inBuf, &outBuf);
  1873.  
  1874.     if (status != SUCCESS) {
  1875.     if (proc_MigDebugLevel > 2) {
  1876.         printf(
  1877.            "%s ProcInitiateMigration: Error returned by host %d:\n\t%s\n",
  1878.            "Warning:", hostID, Stat_GetMsg(status));
  1879.     }
  1880.     } else if (!foreign) {
  1881.     procPtr->peerProcessID = pid;
  1882.     }
  1883.     return(status);
  1884. }
  1885.  
  1886.  
  1887.  
  1888. /*
  1889.  *----------------------------------------------------------------------
  1890.  *
  1891.  * ProcMigCommand --
  1892.  *
  1893.  *    Send a process migration-related command to another host.
  1894.  *    This sets up and performs the RPC itself.
  1895.  *
  1896.  * RPC: Input parameters:
  1897.  *        process ID
  1898.  *        command to perform
  1899.  *        data buffer
  1900.  *    Return parameters:
  1901.  *        ReturnStatus
  1902.  *        data buffer
  1903.  *
  1904.  * Results:
  1905.  *    A ReturnStatus is returned to indicate the status of the RPC.
  1906.  *    The data buffer is filled by the RPC if a result is returned by
  1907.  *    the other host.
  1908.  *
  1909.  * Side effects:
  1910.  *    None.
  1911.  *
  1912.  *----------------------------------------------------------------------
  1913.  */
  1914.  
  1915. ReturnStatus
  1916. ProcMigCommand(host, cmdPtr, inPtr, outPtr)
  1917.     int host;             /* host to send command to */
  1918.     ProcMigCmd *cmdPtr; /* command to send */
  1919.     Proc_MigBuffer *inPtr;     /* pair of <size, ptr> for input */
  1920.     Proc_MigBuffer *outPtr;     /* pair of <size, ptr> for output */
  1921. {
  1922.     ReturnStatus status;
  1923.     Rpc_Storage storage;
  1924.     Proc_TraceRecord record;
  1925.     int maxSize;
  1926.     int toSend;
  1927.  
  1928. #ifndef CLEAN
  1929.     if (proc_DoTrace && proc_MigDebugLevel > 2) {
  1930.     record.processID = cmdPtr->remotePid;
  1931.     record.flags = PROC_MIGTRACE_START;
  1932.     record.info.command.type = cmdPtr->command;
  1933.     record.info.command.data = (ClientData) NIL;
  1934.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_COMMAND,
  1935.              (ClientData) &record);
  1936.     }
  1937. #endif /* CLEAN */   
  1938.  
  1939.     Rpc_MaxSizes(&maxSize, (int *) NIL);
  1940.  
  1941.     /*
  1942.      * Set up for the RPC.
  1943.      */
  1944.     storage.requestParamPtr = (Address) cmdPtr;
  1945.     storage.requestParamSize = sizeof(ProcMigCmd);
  1946.  
  1947.     if (inPtr == (Proc_MigBuffer *) NIL) {
  1948.     storage.requestDataPtr = (Address) NIL;
  1949.     storage.requestDataSize = 0;
  1950.     cmdPtr->totalSize = 0;
  1951.     toSend = 0;
  1952.     } else {
  1953.     toSend = inPtr->size;
  1954.     cmdPtr->totalSize = toSend;
  1955.     }
  1956.     cmdPtr->offset = 0;
  1957.  
  1958.     storage.replyParamPtr = (Address) NIL;
  1959.     storage.replyParamSize = 0;
  1960.  
  1961.     /*
  1962.      * Send the command, breaking it into sizes of at most size maxSize.
  1963.      * Only the last "fragment" can actually return any data.
  1964.      */
  1965.     do {
  1966.     if ((toSend > maxSize) || (outPtr == (Proc_MigBuffer *) NIL)) {
  1967.         storage.replyDataPtr = (Address) NIL;
  1968.         storage.replyDataSize = 0;
  1969.     } else {
  1970.         storage.replyDataPtr = outPtr->ptr;
  1971.         storage.replyDataSize = outPtr->size;
  1972.     }
  1973.     if (inPtr != (Proc_MigBuffer *) NIL) {
  1974.         storage.requestDataPtr = inPtr->ptr + cmdPtr->offset;
  1975.         storage.requestDataSize = (toSend > maxSize) ? maxSize : toSend;
  1976.     }
  1977.  
  1978.     if (proc_MigDebugLevel > 2) {
  1979.         printf("cmd %d totalSize %d offset %d thisDataSize %d\n",
  1980.            cmdPtr->command, cmdPtr->totalSize, cmdPtr->offset,
  1981.            storage.requestDataSize);
  1982.     }
  1983.  
  1984.     status = Rpc_Call(host, RPC_PROC_MIG_COMMAND, &storage);
  1985.  
  1986. #ifndef CLEAN
  1987.     if (proc_DoTrace && proc_MigDebugLevel > 2) {
  1988.         record.flags = 0;
  1989.         Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_COMMAND,
  1990.              (ClientData) &record);
  1991.     }
  1992. #endif                /* CLEAN */   
  1993.  
  1994.     if (status != SUCCESS) {
  1995.         if (proc_MigDebugLevel > 6) {
  1996.         printf("%s ProcMigCommand: error %x returned by Rpc_Call.\n",
  1997.                "Warning:", status);
  1998.         }
  1999.         return(status);
  2000.     }
  2001.     toSend -= maxSize;
  2002.     cmdPtr->offset += maxSize;
  2003.     } while (toSend > 0);
  2004.     return(SUCCESS);
  2005. }
  2006.  
  2007.  
  2008. /*
  2009.  *----------------------------------------------------------------------
  2010.  *
  2011.  * Proc_WaitForMigration --
  2012.  *
  2013.  *    Wait for a process to migrate.  Locks the process and
  2014.  *    then calls a monitored procedure.
  2015.  *
  2016.  * Results:
  2017.  *    None.
  2018.  *
  2019.  * Side effects:
  2020.  *    None.
  2021.  *
  2022.  *----------------------------------------------------------------------
  2023.  */
  2024.  
  2025. ReturnStatus
  2026. Proc_WaitForMigration(processID)
  2027.     Proc_PID processID;
  2028. {
  2029.     Proc_ControlBlock *procPtr;
  2030.     ReturnStatus status;
  2031.  
  2032.     procPtr = Proc_LockPID(processID);
  2033.     if (procPtr == (Proc_ControlBlock *) NIL) {
  2034.     return(PROC_INVALID_PID);
  2035.     }
  2036.     /*
  2037.      * While in the middle of migration, wait on the condition
  2038.      * and then recheck the flags and the processID.
  2039.      * This avoids the possibility of
  2040.      * the procPtr getting recycled while we're waiting.
  2041.      */
  2042.     while (procPtr->genFlags & (PROC_MIG_PENDING | PROC_MIGRATING)) {
  2043.     Proc_Unlock(procPtr);
  2044.         status = WaitForMigration();
  2045.     if (status != SUCCESS) {
  2046.         return(status);
  2047.     }
  2048.     Proc_Lock(procPtr);
  2049.     if (procPtr->processID != processID) {
  2050.         Proc_Unlock(procPtr);
  2051.         return(PROC_INVALID_PID);
  2052.     }
  2053.     }
  2054.     if ((procPtr->genFlags & PROC_MIGRATION_DONE) &&
  2055.     (procPtr->state == PROC_MIGRATED)) {
  2056.     status = SUCCESS;
  2057.     } else {
  2058.     status = FAILURE;
  2059.     }
  2060.     Proc_Unlock(procPtr);
  2061.     
  2062.     return(status);
  2063. }
  2064.  
  2065.  
  2066. /*
  2067.  *----------------------------------------------------------------------
  2068.  *
  2069.  * WaitForMigration --
  2070.  *
  2071.  *    Monitored procedure to wait for a migration condition to be
  2072.  *    signalled.  Higher-level locking actually guarantees that
  2073.  *    a process has actually migrated.
  2074.  *
  2075.  * Results:
  2076.  *    SUCCESS, or GEN_ABORTED_BY_SIGNAL.    
  2077.  *
  2078.  * Side effects:
  2079.  *    Puts current process to sleep.
  2080.  *
  2081.  *----------------------------------------------------------------------
  2082.  */
  2083.  
  2084. static ENTRY ReturnStatus
  2085. WaitForMigration()
  2086. {
  2087.     ReturnStatus status;
  2088.     LOCK_MONITOR;
  2089.     if (Sync_Wait(&migrateCondition, TRUE)) {
  2090.         status = GEN_ABORTED_BY_SIGNAL;
  2091.     } else {
  2092.         status = SUCCESS;
  2093.     }
  2094.     UNLOCK_MONITOR;
  2095.     return(status);
  2096. }
  2097.  
  2098.  
  2099. /*
  2100.  *----------------------------------------------------------------------
  2101.  *
  2102.  * AddMigrateTime --
  2103.  *
  2104.  *    Monitored procedure to add a time to the statistics structure
  2105.  *    atomically.
  2106.  *
  2107.  * Results:
  2108.  *    None.
  2109.  *
  2110.  * Side effects:
  2111.  *    Adds time.
  2112.  *
  2113.  *----------------------------------------------------------------------
  2114.  */
  2115. static ENTRY void
  2116. AddMigrateTime(time, totalPtr, squaredTotalPtr)
  2117.     Time time;
  2118.     unsigned int *totalPtr;
  2119.     unsigned int *squaredTotalPtr;
  2120. {
  2121.     unsigned int intTime;
  2122.     unsigned int squaredTime;
  2123.  
  2124. #ifndef CLEAN
  2125.     LOCK_MONITOR;
  2126.  
  2127.     /*
  2128.      * Round times to hundreds of milliseconds, to keep things
  2129.      * on a low enough scale to keep from overflowing too easily.
  2130.      */
  2131.  
  2132.     intTime = PROC_MIG_TIME_FOR_STATS(time);
  2133.     *totalPtr += intTime;
  2134.     squaredTime = intTime * intTime;
  2135.     *squaredTotalPtr += squaredTime;
  2136.  
  2137.     UNLOCK_MONITOR;
  2138. #endif /* CLEAN */
  2139. }
  2140.  
  2141.  
  2142. /*
  2143.  *----------------------------------------------------------------------
  2144.  *
  2145.  * Proc_MigAddToCounter --
  2146.  *
  2147.  *    Monitored procedure to add a value to a global variable.
  2148.  *    This keeps statistics from being trashed if this were
  2149.  *    executed on a multiprocessor, since incrementing a counter
  2150.  *    isn't necessarily atomic.  If squaredPtr is non-NIL, it
  2151.  *    adds the square of the value to that variable.
  2152.  *
  2153.  * Results:
  2154.  *    None.
  2155.  *
  2156.  * Side effects:
  2157.  *    Updates variable pointed to by intPtr & squaredPtr.
  2158.  *
  2159.  *----------------------------------------------------------------------
  2160.  */
  2161. ENTRY void
  2162. Proc_MigAddToCounter(value, intPtr, squaredPtr)
  2163.     int value;
  2164.     unsigned int *intPtr;
  2165.     unsigned int *squaredPtr;
  2166. {
  2167.  
  2168.     LOCK_MONITOR;
  2169.  
  2170.     *intPtr += value;
  2171.     if (squaredPtr != (unsigned int *) NIL) {
  2172.     *squaredPtr += value * value;
  2173.     }
  2174.  
  2175.     UNLOCK_MONITOR;
  2176. }
  2177.  
  2178. /*
  2179.  *----------------------------------------------------------------------
  2180.  *
  2181.  * ProcRecordUsage --
  2182.  *
  2183.  *    Specialized procedure to update global CPU usages
  2184.  *    atomically.    Because we do some funny arithmetic to store
  2185.  *     the square of a time, we convert timer ticks into times and
  2186.  *     use the function defined above.
  2187.  *
  2188.  * Results:
  2189.  *    None.
  2190.  *
  2191.  * Side effects:
  2192.  *    Adds values.
  2193.  *
  2194.  *----------------------------------------------------------------------
  2195.  */
  2196. void
  2197. ProcRecordUsage(ticks, type)
  2198.     Timer_Ticks ticks;
  2199.     ProcRecordUsageType type;
  2200. {
  2201.     unsigned int *timePtr = (unsigned int *) NIL;
  2202.     unsigned int *squaredTimePtr = (unsigned int *) NIL;
  2203.     Time time;
  2204.  
  2205. #ifndef CLEAN
  2206.  
  2207.     if (type == PROC_MIG_USAGE_REMOTE_CPU) {
  2208.     timePtr = &proc_MigStats.varStats.remoteCPUTime;
  2209.     squaredTimePtr = &proc_MigStats.squared.remoteCPUTime;
  2210.     } else if (type == PROC_MIG_USAGE_TOTAL_CPU) {
  2211.     timePtr = &proc_MigStats.varStats.totalCPUTime;
  2212.     squaredTimePtr = &proc_MigStats.squared.totalCPUTime;
  2213.     proc_MigStats.processes++;
  2214.     } else if (type == PROC_MIG_USAGE_POST_EVICTION) {
  2215.     timePtr = &proc_MigStats.varStats.evictionCPUTime;
  2216.     squaredTimePtr = &proc_MigStats.squared.evictionCPUTime;
  2217.     proc_MigStats.evictionsToUs++;
  2218.     }
  2219.     Timer_TicksToTime(ticks, &time);
  2220.  
  2221.     AddMigrateTime(time, timePtr, squaredTimePtr);
  2222.  
  2223. #endif /* CLEAN */
  2224. }
  2225.  
  2226. /*
  2227.  *----------------------------------------------------------------------
  2228.  *
  2229.  * AccessStats --
  2230.  *
  2231.  *    Access the migration statistics structure atomically.  Individual
  2232.  *    fields may be incremented or decremented outside the lock, but
  2233.  *    looking at the whole structure synchronizes with actions that
  2234.  *    operate on double words, as does resetting it to 0.
  2235.  *
  2236.  *    If copyPtr is NIL, then reset the stats, else copy them.
  2237.  *
  2238.  * Results:
  2239.  *    If requested, a copy of the statistics structure is returned to
  2240.  *    the caller.
  2241.  *
  2242.  * Side effects:
  2243.  *    If requested, the statistics structure is zeroed.
  2244.  *
  2245.  *----------------------------------------------------------------------
  2246.  */
  2247. static ENTRY void
  2248. AccessStats(copyPtr)
  2249.     Proc_MigStats *copyPtr;  /* pointer to area to copy stats into, or NIL */
  2250. {    
  2251.  
  2252.     LOCK_MONITOR;
  2253.  
  2254.     if (copyPtr != (Proc_MigStats *) NIL) {
  2255.     bcopy((Address) &proc_MigStats, (Address) copyPtr,
  2256.           sizeof(Proc_MigStats));
  2257.     } else {
  2258.     bzero((Address) &proc_MigStats, sizeof(Proc_MigStats));
  2259.     proc_MigStats.statsVersion = statsVersion;
  2260.     }
  2261.     
  2262.     UNLOCK_MONITOR;
  2263. }
  2264.  
  2265. /*
  2266.  *----------------------------------------------------------------------
  2267.  *
  2268.  * Proc_MigGetStats --
  2269.  *
  2270.  *    Return migration statistics to the user.
  2271.  *
  2272.  * Results:
  2273.  *    SUCCESS, unless there's a problem copying to user space.
  2274.  *
  2275.  * Side effects:
  2276.  *    None.
  2277.  *
  2278.  *----------------------------------------------------------------------
  2279.  */
  2280. ReturnStatus
  2281. Proc_MigGetStats(addr)
  2282.     Address addr;
  2283. {
  2284.     Proc_MigStats copy;
  2285.     ReturnStatus status;
  2286.  
  2287.     AccessStats(©);
  2288.  
  2289.     status = Vm_CopyOut(sizeof(Proc_MigStats),
  2290.             (Address)©,
  2291.             addr);
  2292.     return(status);
  2293. }
  2294.  
  2295. /*
  2296.  *----------------------------------------------------------------------
  2297.  *
  2298.  * Proc_MigResetStats --
  2299.  *
  2300.  *    Zero the migration statistics structure.
  2301.  *
  2302.  * Results:
  2303.  *    SUCCESS.
  2304.  *
  2305.  * Side effects:
  2306.  *    None.
  2307.  *
  2308.  *----------------------------------------------------------------------
  2309.  */
  2310. ReturnStatus
  2311. Proc_MigResetStats()
  2312. {
  2313.  
  2314.     AccessStats((Proc_MigStats *) NIL);
  2315.     return(SUCCESS);
  2316. }
  2317.  
  2318. /*
  2319.  *----------------------------------------------------------------------
  2320.  *
  2321.  * ProcMigWakeupWaiters --
  2322.  *
  2323.  *    Monitored procedure to signal any processes that may have waited for
  2324.  *    a process to migrate.
  2325.  *
  2326.  * Results:
  2327.  *    None.
  2328.  *
  2329.  * Side effects:
  2330.  *    None.
  2331.  *
  2332.  *----------------------------------------------------------------------
  2333.  */
  2334. ENTRY void
  2335. ProcMigWakeupWaiters()
  2336. {
  2337.  
  2338.     LOCK_MONITOR;
  2339.  
  2340.     Sync_Broadcast(&migrateCondition);
  2341.  
  2342.     UNLOCK_MONITOR;
  2343. }
  2344.  
  2345.  
  2346. /*
  2347.  *----------------------------------------------------------------------
  2348.  *
  2349.  * Proc_MigrateStartTracing --
  2350.  *
  2351.  *    Initialize the tracing variables for process migration.
  2352.  *
  2353.  * Results:
  2354.  *    None.
  2355.  *
  2356.  * Side effects:
  2357.  *    None.
  2358.  *
  2359.  *----------------------------------------------------------------------
  2360.  */
  2361.  
  2362. void
  2363. Proc_MigrateStartTracing()
  2364. {
  2365.     static Boolean init = FALSE;
  2366.  
  2367.     if (!init) {
  2368.     init = TRUE;
  2369.     proc_TraceHdrPtr = &proc_TraceHeader;
  2370.     Trace_Init(proc_TraceHdrPtr, PROC_NUM_TRACE_RECS,
  2371.            sizeof(Proc_TraceRecord), 0);
  2372.     }
  2373.     proc_DoTrace = TRUE;
  2374. }
  2375.  
  2376.  
  2377.  
  2378. /*
  2379.  *----------------------------------------------------------------------
  2380.  *
  2381.  * Proc_DestroyMigratedProc --
  2382.  *
  2383.  *    Kill a process, presumably when its peer host (the home host
  2384.  *    of a foreign process, or the remote host of a migrated process)
  2385.  *    is down.  It may also be done if the process is
  2386.  *    unsuccessfully killed with a signal, even if the remote host
  2387.  *    hasn't been down long enough to be sure it has crashed.
  2388.  *
  2389.  *    This procedure is distinct from Proc_KillRemoteCopy, which issues
  2390.  *     a command to do a similar thing on the host to which the process
  2391.  *     is migrating.  In this case, we're killing our own copy of it.
  2392.  *
  2393.  * Results:
  2394.  *    None.
  2395.  *
  2396.  * Side effects:
  2397.  *    The process is killed.
  2398.  *
  2399.  *----------------------------------------------------------------------
  2400.  */
  2401.  
  2402. void 
  2403. Proc_DestroyMigratedProc(pidData, callInfoPtr) 
  2404.     ClientData pidData;        /* the process ID, as a ClientData */
  2405.     Proc_CallInfo *callInfoPtr;         /* Not used. */
  2406. {
  2407.     Proc_ControlBlock         *procPtr; /* Process to kill. */
  2408.     Proc_PID pid = (Proc_PID) pidData;
  2409.  
  2410.     procPtr = Proc_LockPID(pid);
  2411.     if (procPtr == (Proc_ControlBlock *) NIL) {
  2412.     if (proc_MigDebugLevel > 0) {
  2413.         printf("Warning: Proc_DestroyMigratedProc: process %x not found.\n",
  2414.               (int) pid);
  2415.     }
  2416.     /*
  2417.      * Make sure the dependency on this process goes away.
  2418.      */
  2419.     ProcMigRemoveDependency(pid, TRUE);
  2420.     return;
  2421.     }
  2422.     if ((procPtr->state != PROC_MIGRATED) &&
  2423.     !(procPtr->genFlags & PROC_FOREIGN)) {
  2424.     if (procPtr->genFlags & PROC_MIGRATION_DONE) {
  2425.         /*
  2426.          * Just about to complete the migration.
  2427.          */
  2428.         procPtr->genFlags |= PROC_MIG_ERROR;
  2429.         if (proc_MigDebugLevel > 1) {
  2430.         printf("%s Proc_DestroyMigratedProc: process %x not done migrating.\n",
  2431.               "Warning:", (int) pid);
  2432.         }
  2433.  
  2434.     } else {
  2435.         if (proc_MigDebugLevel > 0) {
  2436.         printf("%s Proc_DestroyMigratedProc: process %x not migrated.\n",
  2437.               "Warning:", (int) pid);
  2438.         }
  2439.     }
  2440.     Proc_Unlock(procPtr);
  2441.     /*
  2442.      * Make sure the dependency on this process goes away.
  2443.      */
  2444.     ProcMigRemoveDependency(pid, TRUE);
  2445.     return;
  2446.     }
  2447.  
  2448.     if (procPtr->state == PROC_NEW && (procPtr->genFlags & PROC_FOREIGN)) {
  2449.     /*
  2450.      * The process was only partially migrated.
  2451.      */
  2452.     if (procPtr->remoteExecBuffer != (Address) NIL) {
  2453.         free(procPtr->remoteExecBuffer);
  2454.         procPtr->remoteExecBuffer = (Address) NIL;
  2455.     }
  2456.     procPtr->state = PROC_DEAD;
  2457.     Proc_CallFunc(Proc_Reaper, (ClientData) procPtr, 0);
  2458.     Proc_Unlock(procPtr);
  2459.     /*
  2460.      * Make sure the dependency on this process goes away.
  2461.      */
  2462.     ProcMigRemoveDependency(pid, TRUE);
  2463.     return;
  2464.     }    
  2465.     
  2466.     
  2467.     if (procPtr->state == PROC_MIGRATED) {
  2468.     /*
  2469.      * Perform an exit on behalf of the process -- it's not
  2470.      * in a state where we can signal it.  The process is
  2471.          * unlocked as a side effect.    We tell
  2472.      * the recovery system that it should try later on to
  2473.      * notify the other host since we aren't able to right now.
  2474.      */
  2475.     ProcExitProcess(procPtr, PROC_TERM_DESTROYED, (int) PROC_NO_PEER, 0,
  2476.             FALSE);
  2477.     ProcMigRemoveDependency(pid, FALSE);
  2478.     /*
  2479.      * Update statistics.
  2480.      */
  2481. #ifndef CLEAN
  2482.     if (proc_MigDoStats) {
  2483.         PROC_MIG_DEC_STAT(remote);
  2484.     }
  2485. #endif /* CLEAN */   
  2486.  
  2487.     } else {
  2488.     /*
  2489.      * Let it get killed the normal way, and let the exit routines
  2490.      * handle cleaning up dependencies.
  2491.      */
  2492.     Sig_SendProc(procPtr, SIG_KILL, (int) PROC_NO_PEER, (Address)0);
  2493.     Proc_Unlock(procPtr);
  2494.     }
  2495.  
  2496. }
  2497.  
  2498.  
  2499. /*
  2500.  *----------------------------------------------------------------------
  2501.  *
  2502.  * Proc_EvictForeignProcs --
  2503.  *
  2504.  *    Evict all foreign processes from this machine.  To do this, send
  2505.  *    each foreign process the SIG_MIGRATE_HOME signal.
  2506.  *
  2507.  * Results:
  2508.  *    If sending any signals returns a non-SUCCESS status, that status
  2509.  *    is returned.  Otherwise, SUCCESS is returned.
  2510.  *
  2511.  * Side effects:
  2512.  *    None.
  2513.  *
  2514.  *----------------------------------------------------------------------
  2515.  */
  2516.  
  2517. ReturnStatus
  2518. Proc_EvictForeignProcs()
  2519. {
  2520.     ReturnStatus status;
  2521.     int numEvicted;        /*  Not used */
  2522.  
  2523. #ifndef CLEAN
  2524.     if (proc_MigDoStats) {
  2525.     PROC_MIG_INC_STAT(evictCalls);
  2526.     }
  2527. #endif /* CLEAN */
  2528.     if (proc_MigStats.foreign == 0) {
  2529.     if (proc_MigDebugLevel > 2) {
  2530.         printf("Proc_EvictForeignProcs: no foreign processes.\n");
  2531.     }
  2532.     return(SUCCESS);
  2533.     }
  2534.     if (EvictionStarted()) {
  2535.     if (proc_MigDebugLevel > 0) {
  2536.         printf("Warning: eviction already in progress.\n");
  2537.     }
  2538.     /*
  2539.      * We really should wait for the previous one to complete and then
  2540.      * start over.  For now, just tell the user we couldn't do it.
  2541.      */
  2542.     return(FAILURE);
  2543.     }
  2544.     status = Proc_DoForEveryProc(Proc_IsEvictable, Proc_EvictProc, TRUE,
  2545.                   &numEvicted);
  2546.     Proc_MigAddToCounter(numEvicted, &proc_MigStats.varStats.evictions,
  2547.              &proc_MigStats.squared.evictions);
  2548.     WaitForEviction();
  2549.     return(status);
  2550. }
  2551.  
  2552.  
  2553. /*
  2554.  *----------------------------------------------------------------------
  2555.  *
  2556.  * Proc_IsEvictable --
  2557.  *
  2558.  *    Return whether the specified process is foreign and is okay
  2559.  *    to migrate.  (This routine is a callback procedure that may be 
  2560.  *    passed as a parameter to routines requiring an arbitrary
  2561.  *    Boolean procedure operating on a PCB.)
  2562.  *
  2563.  * Results:
  2564.  *    Boolean result: TRUE if foreign, FALSE if not.
  2565.  *
  2566.  * Side effects:
  2567.  *    None.
  2568.  *
  2569.  *----------------------------------------------------------------------
  2570.  */
  2571.  
  2572. Boolean
  2573. Proc_IsEvictable(procPtr)
  2574.     Proc_ControlBlock *procPtr;
  2575. {
  2576.     if ((procPtr->genFlags & PROC_FOREIGN) &&
  2577.     !(procPtr->genFlags & PROC_DONT_MIGRATE)) {
  2578.     return(TRUE);
  2579.     } else {
  2580.     return(FALSE);
  2581.     }
  2582. }
  2583.  
  2584.  
  2585. /*
  2586.  *----------------------------------------------------------------------
  2587.  *
  2588.  * Proc_EvictProc --
  2589.  *
  2590.  *    Send a process the SIG_MIGRATE_HOME signal.  Note that if
  2591.  *    the process is not foreign, then the signal will be ignored.
  2592.  *    (This routine is a callback procedure that may be passed as a
  2593.  *        parameter to routines requiring an arbitrary procedure
  2594.  *        operating on a Proc_PID and returning a ReturnStatus.)
  2595.  *
  2596.  * Results:
  2597.  *    The value from Sig_Send is returned.
  2598.  *
  2599.  * Side effects:
  2600.  *    The specified process is signalled.
  2601.  *
  2602.  *----------------------------------------------------------------------
  2603.  */
  2604.  
  2605. ReturnStatus
  2606. Proc_EvictProc(pid)
  2607.     Proc_PID pid;
  2608. {
  2609.     ReturnStatus status = SUCCESS;
  2610.     Proc_ControlBlock *procPtr;
  2611.     
  2612.  
  2613.     procPtr = Proc_LockPID(pid);
  2614.     if (procPtr == (Proc_ControlBlock *) NIL) {
  2615.     if (proc_MigDebugLevel > 2) {
  2616.         printf("Proc_EvictProc: process %x no longer exists.\n", pid);
  2617.     }
  2618.     return (PROC_INVALID_PID);
  2619.     }
  2620.     if (proc_MigDebugLevel > 2) {
  2621.     printf("Proc_EvictProc: evicting process %x.\n", pid);
  2622.     }
  2623.     if ((procPtr->genFlags & PROC_FOREIGN) &&
  2624.     !(procPtr->genFlags & (PROC_DONT_MIGRATE | PROC_DYING)) &&
  2625.     !(procPtr->migFlags & PROC_EVICTING)) {
  2626.     procPtr->migFlags |= PROC_EVICTING;
  2627.     PROC_MIG_INC_STAT(evictionsInProgress);
  2628.     status = Sig_SendProc(procPtr, SIG_MIGRATE_HOME, 0, (Address)0);
  2629.     }
  2630.     Proc_Unlock(procPtr);
  2631.     return(status); 
  2632. }
  2633.  
  2634.  
  2635. /*
  2636.  *----------------------------------------------------------------------
  2637.  *
  2638.  * EvictionStarted --
  2639.  *
  2640.  *    Monitored procedure to initialize variables for recording
  2641.  *    eviction times.
  2642.  *
  2643.  * Results:
  2644.  *    TRUE if an eviction was already in progress, else FALSE.
  2645.  *
  2646.  * Side effects:
  2647.  *    The file-global evictionStarted time variable is initialized.
  2648.  *
  2649.  *----------------------------------------------------------------------
  2650.  */
  2651.  
  2652. static ENTRY Boolean
  2653. EvictionStarted()
  2654. {
  2655.     LOCK_MONITOR;
  2656.  
  2657.     if (proc_MigStats.evictionsInProgress != 0) {
  2658.     UNLOCK_MONITOR;
  2659.     return(TRUE);
  2660.     }
  2661. #ifndef CLEAN
  2662.     if (proc_MigDoStats) {
  2663.     Timer_GetTimeOfDay(&timeEvictionStarted, (int *) NIL, (Boolean *) NIL);
  2664.     }
  2665. #endif /* CLEAN */
  2666.     
  2667.     UNLOCK_MONITOR;
  2668.     return(FALSE);
  2669. }
  2670.  
  2671. /*
  2672.  *----------------------------------------------------------------------
  2673.  *
  2674.  * WaitForEviction --
  2675.  *
  2676.  *    Monitored procedure to record eviction times after eviction has
  2677.  *    completed.  
  2678.  *
  2679.  * Results:
  2680.  *    None.
  2681.  *
  2682.  * Side effects:
  2683.  *    The time taken for eviction is added to the statistics structure.
  2684.  *
  2685.  *----------------------------------------------------------------------
  2686.  */
  2687.  
  2688. static ENTRY void
  2689. WaitForEviction()
  2690. {
  2691.     Time time;
  2692.  
  2693.     LOCK_MONITOR;
  2694.  
  2695.     if (proc_MigStats.evictionsInProgress == 0) {
  2696.     UNLOCK_MONITOR;
  2697.     return;
  2698.     }
  2699.     while (proc_MigStats.evictionsInProgress != 0) {
  2700.     if (Sync_Wait(&evictCondition, TRUE)) {
  2701.         /*
  2702.          * Interrupted.  Just give up.
  2703.          */
  2704.         proc_MigStats.evictionsInProgress = 0;
  2705.         UNLOCK_MONITOR;
  2706.         return;
  2707.     }
  2708.     }
  2709. #ifndef CLEAN
  2710.     if (proc_MigDoStats) {
  2711.     int intTime;
  2712.     int squaredTime;
  2713.  
  2714.     Timer_GetTimeOfDay(&time, (int *) NIL, (Boolean *) NIL);
  2715.     Time_Subtract(time, timeEvictionStarted, &time);
  2716.     intTime = PROC_MIG_TIME_FOR_STATS(time);
  2717.     squaredTime = intTime * intTime;
  2718.     proc_MigStats.varStats.totalEvictTime += intTime;
  2719.     proc_MigStats.squared.totalEvictTime += squaredTime;
  2720.  
  2721.     proc_MigStats.evictsNeeded++;
  2722.     }
  2723. #endif /* CLEAN */   
  2724.     UNLOCK_MONITOR;
  2725. }
  2726.  
  2727. /*
  2728.  *----------------------------------------------------------------------
  2729.  *
  2730.  * ProcMigEvictionComplete --
  2731.  *
  2732.  *    Monitored procedure to signal the process that is recording eviction
  2733.  *    statistics.  This is done any time an eviction completes. When
  2734.  *    the count of evictions hits zero, we wake up the process waiting for
  2735.  *     eviction.  If the count of foreign processes ever hits 0 we also
  2736.  *     know all evictions are complete -- this is a double-check against
  2737.  *    losing track of a process during eviction if something unexpected
  2738.  *    happens (such as if it gets "destroyed").
  2739.  *
  2740.  * Results:
  2741.  *    None.
  2742.  *
  2743.  * Side effects:
  2744.  *    Notifies waiting process.
  2745.  *
  2746.  *----------------------------------------------------------------------
  2747.  */
  2748. ENTRY void
  2749. ProcMigEvictionComplete()
  2750. {
  2751.  
  2752.     LOCK_MONITOR;
  2753.  
  2754.     if (proc_MigStats.foreign == 0) {
  2755.     proc_MigStats.evictionsInProgress = 0;
  2756.     } else if (proc_MigStats.evictionsInProgress != 0) {
  2757.     proc_MigStats.evictionsInProgress--;
  2758.     }
  2759.     if (proc_MigStats.evictionsInProgress == 0) {
  2760.     Sync_Broadcast(&evictCondition);
  2761.     }
  2762.  
  2763.     UNLOCK_MONITOR;
  2764. }
  2765.  
  2766. /*
  2767.  *----------------------------------------------------------------------
  2768.  *
  2769.  * Proc_NeverMigrate --
  2770.  *
  2771.  *    Flag a process so it will never be migrated.  This may be
  2772.  *     used to keep the master of a pseudo-device from migrating, or
  2773.  *     a process with kernel addresses mapped into user space from
  2774.  *    migrating.  The process is flagged as unmigrateable for the rest of
  2775.  *     the lifetime of the process.
  2776.  *
  2777.  * Results:
  2778.  *    None.
  2779.  *
  2780.  * Side effects:
  2781.  *    The process's genFlags field is modified.
  2782.  *
  2783.  *----------------------------------------------------------------------
  2784.  */
  2785.  
  2786. void
  2787. Proc_NeverMigrate(procPtr)
  2788.     Proc_ControlBlock *procPtr;
  2789. {
  2790.  
  2791.     Proc_Lock(procPtr);
  2792.     if (proc_MigDebugLevel > 4) {
  2793.     printf("Proc_NeverMigrate: don't migrate process %x.\n",
  2794.            procPtr->processID);
  2795.     }
  2796.     if (!(procPtr->genFlags & PROC_DONT_MIGRATE)) {
  2797.     procPtr->genFlags |= PROC_DONT_MIGRATE;
  2798.     if (procPtr->genFlags & PROC_FOREIGN) {
  2799.         if (proc_MigDebugLevel > 3) {
  2800.         printf("Proc_NeverMigrate: process %x is foreign.\n",
  2801.                procPtr->processID);
  2802.         }
  2803.         PROC_MIG_DEC_STAT(foreign);
  2804.     }
  2805.     }
  2806.     Proc_Unlock(procPtr);
  2807. }
  2808.  
  2809.  
  2810. /*
  2811.  *----------------------------------------------------------------------
  2812.  *
  2813.  * Proc_GetEffectiveProc --
  2814.  *
  2815.  *    Get a pointer to the Proc_ControlBlock for the process that is
  2816.  *    *effectively* running on the current processor.  Thus, for an
  2817.  *    RPC server performing a system call on behalf of a migrated process,
  2818.  *    the "effective" process will be the process that invoked the system
  2819.  *    call.  In all other cases, the "effective" process will be the
  2820.  *    same as the "actual" process.
  2821.  *
  2822.  * Results:
  2823.  *    A pointer to the process is returned.  If no process is active,
  2824.  *    NIL is returned.
  2825.  *
  2826.  * Side effects:
  2827.  *    None.
  2828.  *
  2829.  *----------------------------------------------------------------------
  2830.  */
  2831. Proc_ControlBlock *
  2832. Proc_GetEffectiveProc()
  2833. {
  2834.     Proc_ControlBlock *procPtr;
  2835.  
  2836.     procPtr = proc_RunningProcesses[Mach_GetProcessorNumber()];
  2837.     if (procPtr == (Proc_ControlBlock *) NIL ||
  2838.         procPtr->rpcClientProcess ==  (Proc_ControlBlock *) NIL) {
  2839.     return(procPtr);
  2840.     }
  2841.     return(procPtr->rpcClientProcess);
  2842. }
  2843.  
  2844.  
  2845. /*
  2846.  *----------------------------------------------------------------------
  2847.  *
  2848.  * Proc_SetEffectiveProc --
  2849.  *
  2850.  *    Set the "effective" process on the current processor.  If the
  2851.  *    process is (Proc_ControlBlock) NIL, the effective process is
  2852.  *    the same as the real process.
  2853.  *
  2854.  * Results:
  2855.  *    None.  
  2856.  *
  2857.  * Side effects:
  2858.  *    The "rpcClientProcess" field of the current process's
  2859.  *    Proc_ControlBlock is set to hold the effective process.
  2860.  *
  2861.  *----------------------------------------------------------------------
  2862.  */
  2863. void
  2864. Proc_SetEffectiveProc(procPtr)
  2865.     Proc_ControlBlock *procPtr;
  2866. {
  2867.     Proc_ControlBlock *actualProcPtr;
  2868.  
  2869.     actualProcPtr = Proc_GetActualProc();
  2870.     if (actualProcPtr == (Proc_ControlBlock *) NIL) {
  2871.     panic("Proc_SetEffectiveProcess: current process is NIL.\n");
  2872.     } else {
  2873.     actualProcPtr->rpcClientProcess = procPtr;
  2874.     }
  2875. }
  2876.  
  2877.